JavaScriptで複数の配列の要素をランク順にマッピングする方法
問題の概要
ここに、次のような3つの数値型JavaScript配列があると仮定します。
const array1 = [10,23,53,74,33,56,6,0,43,45,11]; const array2 = [52,46,27,28,4,11,53,6,75,75,22]; const array3 = [26,18,10,12,31,12,5,8,44,34,65];
すべての配列の長さは常に同じであるとします。
求められているのは、任意の数の配列を受け取り、すべての配列を通して対応する位置にある要素同士を比較し、その大小関係(降順)に基づいてランク(順位)を割り当てるJavaScript関数を作成することです。
つまり、各インデックス位置について、複数の配列から取り出した値をまとめて降順に並べ、大きい方から「1、2、3…」という順位を振っていきます。
したがって、上記の配列の場合、出力は次のようになります。
const array1 = [3,2,1,1,1,1,2,3,2,2,3]; const array2 = [1,1,2,2,2,2,1,2,1,1,2]; const array3 = [2,3,3,3,3,3,3,1,2,3,1];
解決のアプローチ
この問題を解くための手順は以下の通りです。
- 転置(transpose)処理: 複数の配列を、同じインデックスの要素が同じ行に集まるように変換します。これにより、各位置ごとの比較対象がグループ化されます。
- ランク計算: 各グループ内の値を降順にソートし、Mapを使って重複する値には同じ順位を割り当てながら、それぞれの値の順位を決定します。
- 再転置: 計算した順位を元の配列構造に戻すために、再度転置を行います。
コード例
以下がその実装コードです。
const array1 = [10,23,53,74,33,56,6,0,43,45,11];
const array2 = [52,46,27,28,4,11,53,6,75,75,22];
const array3 = [26,18,10,12,31,12,5,8,44,34,65];
// 配列を行と列を入れ替えるように変換する関数
const transpose = (rank, arr) => {
return arr.map((el, ind) => {
return [...(rank[ind] || []), el];
});
};
// 各グループ内の値に対して降順のランクを割り当てる関数
const ranks = arr => {
return arr.map(
Map.prototype.get,
[...arr]
.sort((a, b) => b - a)
.reduce((r => (m, v) => m.set(v, (r++, m.get(v)) || r))(0), new Map)
);
};
// 全体の処理を組み合わせるメイン関数
const findRanks = (...arrs) => {
return arrs
.reduce(transpose, [])
.map(ranks)
.reduce(transpose, []);
};
console.log(findRanks(array1, array2, array3));
コードの解説
transpose関数は、reduceと組み合わせて使うことで、複数の配列を「同じインデックスの要素が縦に並ぶ」形式へ変換します。これにより、例えば最初の要素同士(10、52、26)がひとつのグループになります。
ranks関数では、各グループのコピーを降順にソートし、Mapオブジェクトを使って「値 → 順位」の対応表を作成しています。この実装では、同点の値にも連続した番号が振られる点に注意してください。最後にfindRanks関数が、転置→ランク計算→再転置の一連の流れを実行し、元の配列と同じ形状でランク付きの結果を返します。
出力結果
コンソールには次の出力が表示されます。
[ [ 3, 2, 1, 1, 1, 1, 2, 3, 3, 2, 3 ], [ 1, 1, 2, 2, 3, 3, 1, 2, 1, 1, 2 ], [ 2, 3, 3, 3, 2, 2, 3, 1, 2, 3, 1 ] ]
このように、各配列の各要素が、同じ位置にある他の配列の要素と比較した際の順位(降順)に置き換えられています。この手法は、配列の数や長さが変わっても汎用的に動作するため、さまざまなデータ比較のシーンで応用できます。
-
【初心者向け】JavaScriptのreverse()メソッドで配列を逆順にする方法
JavaScriptのreverse()メソッドは、配列の要素を元の順序と逆順に入れ替えるための便利な関数です。このメソッドを呼び出すと、配列の最初の要素が最後に、最後の要素が最初に移動し、配列全体が反転されます。reverse()メソッドの基本reverse()は配列そのものを変更する「破壊的メソッド」である点に注意してください。つまり、元の配列の順序が直接書き換えられます。元の配列を保持したい場合は、あらかじめslice()やスプレッド構文([...arr])などでコピーを作成してからreverse()を使用するのがおすすめです。サンプルコード以下は、ボタンをクリックすると配列の要素が逆順
-
JavaScriptにおける配列の分割代入(Destructuring)の基本と使い方
分割代入(Destructuring)とは、配列から値を取り出して個別の変数に展開するための構文です。ES2015(ES6)で導入されたこの機能を使うと、配列の各要素を簡潔かつ読みやすく変数に割り当てることができます。 配列の分割代入のサンプルコード 以下は、JavaScriptで配列の分割代入を行うコード例です。 <!DOCTYPE html> <html lang="ja"> <head> <meta charset="UTF-8" /> <meta name="viewport&quo