「配列内のオブジェクト」ということなので、以下のようなコードで実験用の配列を作成していきます。
/*---配列内にオブジェクトを収めるサンプルコード ---*/
const arr = [...Array(10)].map((_, i) => {
return {
index: i + 1,
number: (Math.random() * 100),
}
})
console.log(arr);
// 結果
[{
index: 1,
number: 91.25240273034892
}, {
index: 2,
number: 50.30337793565278
}, {
index: 3,
number: 56.7219849866174
}, {
index: 4,
number: 78.14357103773145
}, {
index: 5,
number: 56.00559517743395
}, {
index: 6,
number: 83.7587424204647
}, {
index: 7,
number: 97.54322322663951
}, {
index: 8,
number: 96.49660404863312
}, {
index: 9,
number: 24.422683577051842
}, {
index: 10,
number: 78.23240765349418
}]
- 要素数10の配列、要素にオブジェクト
- 「number」の値はrandom()なので実行毎に数値が変わる
- map()のreturnをオブジェクトに出来ることが地味にビックリ
やりたい事
- 各「number」の値を比較して、ランキングを作成したい
- sort()系を使い、値の比較と並び替え
- 配列要素を順番に取り出し、ベストやワーストを出す
そして、作成したのが以下のコードになります。
/*---ランキングを作るコード ---*/
const ranking = (arr, key, n) => {
const arr2 = arr.toSorted((a, b) => (b[key] - a[key]) * Math.sign(n));
const order = [...Array(Math.abs(n)).keys()]
.map(e => arr2.at(e));
order.unshift({
index: 0,
title:`${n > 0 ? 'ベスト': 'ワースト'}${Math.abs(n)}`,
});
return order;
}
const bestRank = ranking(arr, 'number', 3);
const worstRank = ranking(arr, 'number', -3);
console.log(bestRank);
// 結果
[{
index: 0,
title: "ベスト3"
}, {
index: 7,
number: 97.54322322663951
}, {
index: 8,
number: 96.49660404863312
}, {
index: 1,
number: 91.25240273034892
}]
console.log(worstRank);
// 結果
[{
index: 0,
title: "ワースト3"
}, {
index: 9,
number: 24.422683577051842
}, {
index: 2,
number: 50.30337793565278
}, {
index: 5,
number: 56.00559517743395
}]
.toSorted()
通常、sort()で昇順、降順をさせようと思った時、
- sort((a, b) => a - b) 昇順
- sort((a, b) => b - a) 降順
と紹介されている事が多いのですが、コード的に aとb をひっくり返すのが何故か 面倒くさい と思ってしまいました。
とりあえず、b-a に1か-1を掛け算したら、上手く昇順と降順が表現できたので、一先ずこれでOKとしました。
尚、toSorted()は、sort()の非破壊的版 らしいです。積極的に使っていきたいです。
.at()
配列のインデックス番号を指定して読み込みに行くメソッドです。
今までのarr2[i]を使っても良かったのですが、arr2.at(i)がカッコ良さそうな感じがして、なんとなく使って見ました(笑)
今回の昇順降順に関しては、arr2.at(i) で i の値を
- 0,1,2
- -1,-2,-3
とすることでランキングのベストとワーストを出せたハズで、そういったコードも作る事は出来たと思うのですが、今回は .toSorted() に任せる事としました。
.find()、最大値
次に、ランキングではないのですが、最大値を持つオブジェクトも出してみようと思います。
/*--- 最大値 を検索、.find()で抽出するコード ---*/
const maxNum = arr.reduce((a, c) => Math.max(a, c.number), 0);
const maxObj = arr.find(e => e.number == maxNum);
console.log(maxObj);
// 結果
{
index: 7,
number: 97.54322322663951
}
.filter()、~未満
ついでに、~未満 も抽出してみます。
/*--- ~未満 を.filter()で抽出するコード ---*/
const belowObj = arr.filter(e => e.number < 55);
console.log(belowObj);
// 結果
[{
index: 2,
number: 50.30337793565278
}, {
index: 9,
number: 24.422683577051842
}]
比較条件を別に算出している場合は、.find() や .filter() を使い元のarrから該当要素を抽出する事も出来ますね。
まとめ
- オブジェクトの値を比較して、配列内のオブジェクトを直接ソート が可能
- オブジェクトの値で .find() や .filter() をすると、オブジェクト自体の抽出 が可能
という事で、
- もっと良い方法があるよ
- もっと簡潔に書けるよ
- それ、まちがってるよ
などありましたら、コメントでお待ちしています。
参考記事