【JavaScript】配列の配列から重複する共通のサブ配列を除外してユニークな配列を取得する方法
問題の概要
JavaScriptでは、配列の中にさらに配列が格納された「配列の配列(ネストされた配列)」を扱う場面が多くあります。例えば、以下のようなデータを考えてみましょう。
const arr = [ [ "Serta", "Black Friday" ], [ "Serta", "Black Friday" ], [ "Simmons", "Black Friday" ], [ "Simmons", "Black Friday" ], [ "Simmons", "Black Friday" ], [ "Simmons", "Black Friday" ] ];
上記の配列には、まったく同じ内容のサブ配列が複数含まれています。ここで求められるのは、元の配列から重複するサブ配列をすべて除外し、ユニークなサブ配列のみを持つ新しい配列を返すJavaScript関数を実装することです。
本記事では、その具体的な実装方法と内部の仕組みについて詳しく解説します。
実装コード
実際のコードは以下のとおりです。
const arr = [
[
"Serta",
"Black Friday"
],
[
"Serta",
"Black Friday"
],
[
"Simmons",
"Black Friday"
],
[
"Simmons",
"Black Friday"
],
[
"Simmons",
"Black Friday"
],
[
"Simmons",
"Black Friday"
]
];
const filterCommon = arr => {
const map = Object.create(null);
let res = [];
res = arr.filter(el => {
const str = JSON.stringify(el);
const bool = !map[str];
map[str] = true;
return bool;
});
return res;
};
console.log(filterCommon(arr));
コードの仕組み
この関数がどのように動作しているのか、ポイントを整理してみましょう。
- JSON.stringify()による文字列化: 配列同士を直接比較すると参照の一致しか判定できません。そこで各サブ配列を
JSON.stringify()で文字列に変換し、比較可能なキーを作成します。 - オブジェクトによる重複管理:
Object.create(null)で生成したプロトタイプを持たないプレーンなオブジェクトをマップとして使用し、一度出現した文字列キーを記録します。これにより、意図しないキーの衝突を防げます。 - filter()による絞り込み: マップに未登録のキーを持つ要素だけが
trueを返すため、初めて出現したサブ配列のみが結果に残ります。
出力結果
コンソールには以下のように出力されます。
[ [ 'Serta', 'Black Friday' ], [ 'Simmons', 'Black Friday' ] ]
ご覧のとおり、「Serta」と「Simmons」の組み合わせがそれぞれ1つずつ残り、重複していたサブ配列はすべて除外されました。また、元の配列は変更されず、新しい配列が返される点も重要なポイントです。
注意点:要素の順序について
この方法では、サブ配列内の要素の並び順が異なる場合(例:["Black Friday", "Serta"])は別の配列として扱われます。順序を無視して重複判定を行いたい場合は、文字列化する前にsort()で要素を並べ替えておくなどの工夫が必要です。
-
JavaScriptで配列をreduceする方法|reduce()メソッドで配列要素を合計する
JavaScriptのreduce()メソッドは、配列の各要素を先頭から順に処理し、その結果を1つの値にまとめる(畳み込む)ための配列メソッドです。数値の合計を求めるだけでなく、配列からオブジェクトを組み立てたり、条件に応じてデータを集約したりと、幅広い場面で活用されています。reduce()メソッドの基本構文 { return 戻り値; }, 初期値);accumulator(アキュムレータ):直前のコールバック関数が返した値(累積値)。最初のループでは初期値、または配列の第1要素が代入されます。currentValue:現在処理している配列の要素。初期値:累積値の出発点となる値。省略し
-
JavaScriptでオブジェクトを含む「配列の配列」をループ処理する方法
JavaScriptでオブジェクトを含む多次元配列をループするには?JavaScriptでは、オブジェクトを含む配列の配列(入れ子構造の配列)をループ処理する際、forEach()メソッドをネストして使用し、さらにfor...inループで各オブジェクトのプロパティにアクセスするのが一般的な方法です。以下に、具体的な実装例を紹介します。コード例<!DOCTYPE html> <html lang=ja> <head> <meta charset=UTF-8 /> <meta name=viewport content=width=device