やめ太郎先生のところで、lodash の多段階のソートが紹介されていました。
ワイ「なに!?ライブラリをラップするやと!?」 - Qiita
https://qiita.com/Yametaro/items/111ce26637d6a3c2e763
const userList = [
{
name: 'c',
age: 20,
},
{
name: 'b',
age: 20,
},
{
name: 'a',
age: 20,
},
{
name: 'c',
age: 21,
},
];
const sortedUserList = _.orderBy(userList, ['name', 'age'], ['asc', 'desc'])
console.log(sortedUserList)
// [[object Object] {
// age: 20,
// name: "a"
// }, [object Object] {
// age: 20,
// name: "b"
// }, [object Object] {
// age: 21,
// name: "c"
// }, [object Object] {
// age: 20,
// name: "c"
// }]
パラメータ指定によって項目内部のnameとageで、降順、昇順が指定できるようになっているようです。
sort関数は書いたことがあったのですが、複数条件でのソートを考慮するのを忘れていました。
partsjs/array.test.js at v9.0.0 · standard-software/partsjs
https://github.com/standard-software/partsjs/blob/v9.0.0/source/array/array.test.js#L2385
複数条件でのソートは普通、いろんな場面で使いそうなので実装してみました。
const orderFuncFromName = name => {
if (name === 'asc') {
return (a, b) => (
a > b ? 1
: a < b ? -1
: 0
);
} else {
return (a, b) => (
a > b ? -1
: a < b ? 1
: 0
);
}
}
const sort = (array, orderFuncs) => {
const orderFuncArray = [];
for (const [orderName, func] of orderFuncs) {
const orderFunc = orderFuncFromName(orderName);
orderFuncArray.push((a, b) => orderFunc(func(a), func(b)));
}
array.sort((a, b) => {
for (const orderFuncItem of orderFuncArray) {
const result = orderFuncItem(a, b);
if (result !== 0) {
return result;
}
}
return 0;
});
};
const sortedUserList = [...userList];
sort(sortedUserList, [
['asc', v => v.name],
['desc', v => v.age],
]);
console.log(sortedUserList)
思った以上にわかりやすく短めに書けました。
これで項目内の文字列の内容や長さや数値でのソートが書きやすくなりそう。