JavaScriptで2つの配列の一意な共通要素(積集合)を抽出する方法
本記事では、2つの数値の配列(arr1 と arr2)を受け取り、両方の配列に存在する共通要素、つまり「積集合」に相当する要素を取り出す JavaScript の関数を作成します。
重要な条件がひとつあります。それは、一度共通要素として検出した値は、その後どちらの配列に再び現れたとしても、二度と結果に含めてはいけないという点です。つまり、結果には重複のない一意な共通要素のみを格納する必要があります。
入力と出力の例
たとえば、次のような入力配列が与えられた場合を考えてみましょう。
const arr1 = [1, 5, 7, 3, 1]; const arr2 = [1, 7, 3, 1, 6];
このとき、期待される出力は次のようになります。
const output = [1, 3, 7];
出力される要素の順序自体はそれほど重要ではありません。重要なのは、同じ共通要素を何度も結果に含めないことです。
実装コード
以下が実際のコードです。
const arr1 = [1, 5, 7, 3, 1];
const arr2 = [1, 7, 3, 1, 6];
const uniqueIntersection = (arr1, arr2) => {
const map = new Set();
const res = [];
// arr1 の全要素を Set に登録
arr1.forEach(el => map.add(el));
// arr2 の要素が Set に存在すれば結果に追加し、
// 重複防止のため Set から削除する
arr2.forEach(el => {
if (map.has(el)) {
res.push(el);
map.delete(el);
}
});
return res;
};
console.log(uniqueIntersection(arr1, arr2));コードの解説
この実装のポイントは、Set オブジェクトを活用しているところです。処理の流れは以下のとおりです。
- まず
arr1のすべての要素をSetに追加します。Setは内部的に重複を自動的に排除するため、arr1内の重複値はここでまとめられます。 - 次に
arr2を走査し、各要素がSetに存在するかどうかをhas()メソッドで判定します。 - 存在する場合は結果配列
resに push したうえで、delete()メソッドでその要素をSetから削除します。この削除処理こそが、同一要素が二度目に出現した際に再びカウントされないようにする仕組みです。 - 最後に
resを返せば、一意な共通要素のみが格納された配列が得られます。
Set の検索・追加・削除はいずれも平均 O(1) で動作するため、このアプローチは全体の計算量が O(n + m)(n、m はそれぞれの配列の長さ)となり、ネストしたループで総当たり的に比較する方法よりも大幅に効率的です。
実行結果
コンソールには次のように出力されます。
[1, 7, 3]
ご覧のとおり、1 が両方の配列に複数回登場していますが、結果には一度だけ含まれており、「一意な共通部分」の要件を正しく満たしています。
-
JavaScriptのconstとletの違いを徹底解説!ブロックスコープ変数の基本と使い方
JavaScriptにおけるconstとletの基本const と let は、ES2015(ES6)で導入された変数宣言用のキーワードです。どちらもブロックスコープ(波括弧 { } で囲まれた範囲)に対応しているのが特徴で、関数スコープしか持たなかった従来の var とは異なる挙動を示します。両者の大きな違いは再代入の可否です。letで宣言した変数は後から何度でも値を再代入できますが、constで宣言した変数は再代入しようとするとエラー(TypeError)が発生します。letとconstの主な違い項目letconst再代入可能不可(エラー発生)スコープブロックスコープブロックスコープ宣言時
-
JavaScriptにおける配列とSetの違いとは?重複値の扱いと要素アクセスをわかりやすく解説
JavaScriptのSet(セット)オブジェクトは、ES2015(ES6)で新たに導入されたデータ型です。従来から広く使われている配列(Array)と比べると、いくつか重要な違いがあります。 配列とSetの主な違い 重複した値の扱い: 配列は同じ値をいくつでも格納できますが、Setでは同一の値は1つしか保持されません。重複した値は自動的に除外されるのが大きな特徴です。 要素へのアクセス方法: 配列ではインデックス(例:arr[0])を使って任意の位置の要素へ直接アクセスできます。一方、Setにはインデックスの概念がなく、要素は挿入された順序どおりに先頭から順番に辿ることしかできません。