JavaScript で 2つの配列を重複せずに結合する

Moataz Farid 2023年10月12日
  1. ECMAScript 6 のスプレッド構文を使った JavaScript の配列のマージ
  2. ECMAScript 5 の Array.concat 関数を用いた JavaScript の配列マージ
  3. for ループを使って配列から重複を削除する
  4. JavaScript による ECMAScript 6 の Array.prototype を用いた配列からの重複配列の削除
  5. JavaScript で ECMAScript 5 で Object.defineProperty を使用して配列から重複要素を削除する
  6. Lo-Dash または Underscore.js を使用してマージし、一意の値のみを保持する
  7. ECMAScript 6 の Set を使ったマージとユニークな値のみの保持
  8. O(n) だけの複雑さで for ループと Dictionary を使用して重複しない値をマージする
JavaScript で 2つの配列を重複せずに結合する

このチュートリアルでは、JavaScript で 2つの配列を重複せずにマージする方法を学びます。

まず、ES5 と ES6 の両方のバージョンで異なるマージ方法を紹介します。

次に、異なるメソッドを使用して重複を削除する方法を学びます。

最後に、独自の関数を書いたり、外部ライブラリを使ったりして、たった 1 ステップで操作を行う方法を学びます。

ここでは、2つの配列 arrayAarrayB があり、それらを arrayC にマージしたいとします。

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

ECMAScript 6 のスプレッド構文を使った JavaScript の配列のマージ

スプレッド構文(...)は、配列のような要素が想定される場所や、関数の中で 0 以上の引数が想定される場所などで、反復可能な要素の内容を展開するために使われます。

var arr = [2, 4];

function add(x, y) {
  return x + y;
}

console.log(add(...arr));

では、このスプレッド構文を使って配列を arrayC にマージしてみましょう。

arrayC = [...arrayA, ...arrayB];
console.log(arrayC);

コード例

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

//merging using the spread syntax
arrayC = [...arrayA,...arrayB];
console.log("Merged Using Spread Syntax >"+arrayC);

出力:

Array A > Java,JavaScript
Array B > C#,PHP,Java
Merged Using Spread Syntax >Java,JavaScript,C#,PHP,Java

ECMAScript 5 の Array.concat 関数を用いた JavaScript の配列マージ

Array.concat を用いた結合は、入力配列 ( arrayB ) の内容を元の配列 ( arrayA ) の内容と結合するために用いられます。

arrayC = arrayA.concat(arrayB);
console.log(arrayC);

結果の配列から重複しているものを削除したい場合は、複数の方法がありますので、その方法を見てみましょう。

例:

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

//merging using Array.concat function in ECMAScript 5
arrayC = arrayA.concat(arrayB);
console.log("Merged Using Array.concat function >"+arrayC);

出力:

Array A > Java,JavaScript
Array B > C#,PHP,Java
Merged Using Array.concat function >Java,JavaScript,C#,PHP,Java

for ループを使って配列から重複を削除する

重複を取り除く最も簡単な方法は、独自の入れ子になった for ループを作成することです。

私たちのアルゴリズムは次のようになります。

  1. 入力配列 inArray からクローンを作成し、元の配列を変更しないようにします。
  2. arr.splice() を使って重複している要素を見つけて削除するための入れ子ループを作成します。外側は n から始まり、内側は n+1 から始まる。
function removeDuplicates(inArray) {
  var arr =
      inArray
          .concat()  // create a clone from inArray so not to change input array
  // create the first cycle of the loop starting from element 0 or n
  for (var i = 0; i < arr.length; ++i) {
    // create the second cycle of the loop from element n+1
    for (var j = i + 1; j < arr.length; ++j) {
      // if the two elements are equal , then they are duplicate
      if (arr[i] === arr[j]) {
        arr.splice(j, 1);  // remove the duplicated element
      }
    }
  }
  return arr;
}

そして、他の関数と同様に removeDuplicates 関数を使用することができます。

var arrayWithoutDuplicates = removeDuplicates(arrayC);
console.log(arrayWithoutDuplicates);

例:

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

//removing duplicates from an array using nested for loop

function removeDuplicates(inArray){
    var arr = inArray.concat() // create a clone from inArray so not to change input array
    //create the first cycle of the loop starting from element 0 or n
    for(var i=0; i<arr.length; ++i) {
        //create the second cycle of the loop from element n+1
        for(var j=i+1; j<arr.length; ++j) {
            //if the two elements are equal , then they are duplicate
            if(arr[i] === arr[j]) {
                arr.splice(j, 1); //remove the duplicated element 
            }
        }
    }
    return arr;
}
arrayC = arrayA.concat(arrayB);
console.log("Merged arrayC > "+ arrayC );
console.log("Removing duplicates using removeDuplicates > "+ removeDuplicates(arrayC) );

出力:

Array A > Java,JavaScript
Array B > C#,PHP,Java
Merged arrayC > Java,JavaScript,C#,PHP,Java
Removing duplicates using removeDuplicates > Java,JavaScript,C#,PHP

JavaScript による ECMAScript 6 の Array.prototype を用いた配列からの重複配列の削除

ECMAScript 6 が使えるようになったら、Array.prototype を使って重複を削除することもできます。

プロトタイプとは何を意味するのか?プロトタイプとは、JavaScript におけるすべての関数やオブジェクトに関連付けられたオブジェクトのようなものです。

それでは、Array.prototype をどのように使うか見てみましょう。

私たちのアルゴリズムは次のようになります。

  1. 配列オブジェクト this.concat() からクローンを作成し、元の配列を変更しないようにします。
  2. arr.splice() を用いて重複している要素を見つけて削除するための入れ子ループを作成します。外側は n から始まり、内側は n+1 から始まる。
Array.prototype.removeDuplicates = function() {
  var arr = this.concat();  // create a clone from the input so not to change
                            // the source
  // create the first cycle of the loop starting from element 0 or n
  for (var i = 0; i < arr.length; ++i) {
    // create the second cycle of the loop from element n+1
    for (var j = i + 1; j < arr.length; ++j) {
      // if the two elements are equal , then they are duplicate
      if (arr[i] === arr[j]) {
        arr.splice(j, 1);  // remove the duplicated element
      }
    }
  }
  return arr;
}

そして、そのプロトタイプを呼び出すと、次のようになります。

var arrayWithoutDuplicates = arrayC.removeDuplicates();
console.log(arrayWithoutDuplicates);

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

arrayC = arrayA.concat(arrayB);


//removing duplicates from an array using Array.prototype in ECMAScript 6
Array.prototype.removeDuplicatesPrototype = function() {
   var arr = this.concat(); // get the input array
   //create the first cycle of the loop starting from element 0 or n
   for(var i=0; i<arr.length; ++i) {
       //create the second cycle of the loop from element n+1
       for(var j=i+1; j<arr.length; ++j) {
           //if the two elements are equal , then they are duplicate
           if(arr[i] === arr[j]) {
               arr.splice(j, 1); //remove the duplicated element 
           }
       }
   }
   return arr;
}
console.log("Merged arrayC > "+arrayC);
console.log("Removing duplicates using removeDuplicatesPrototype > "+arrayC.removeDuplicatesPrototype());

JavaScript で ECMAScript 5 で Object.defineProperty を使用して配列から重複要素を削除する

ECMAScript 5 しか使えないのであれば、Object.defineProperty を使って独自のプロパティを作成すれば、Array 型のすべての要素から重複を取り除くことができます。

ここでは、Array.prototype と入力してプロパティの型を配列のプロトタイプとして定義します。プロパティの名前は removeDuplicates のように次のパラメータとして挿入する必要があります。

どのように正しく書かれているか見てみましょう。

Object.defineProperty(Array.prototype, 'removeDuplicates', {
  // defining the type and name of the property
  enumerable: false,
  configurable: false,
  writable: false,
  value: function() {
    var arr = this.concat();  // get the input array
    // create the first cycle of the loop starting from element 0 or n
    for (var i = 0; i < arr.length; ++i) {
      // create the second cycle of the loop from element n+1
      for (var j = i + 1; j < arr.length; ++j) {
        // if the two elements are equal , then they are duplicate
        if (arr[i] === arr[j]) {
          arr.splice(j, 1);  // remove the duplicated element
        }
      }
    }
    return arr;
  }
});

このようにしてプロパティを直接呼び出すことができます。

var arrayWithoutDuplicates = arrayC.removeDuplicates();
console.log(arrayWithoutDuplicates);

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

arrayC = arrayA.concat(arrayB);

//removing duplicates from an array using defineProperty in ECMAScript 5
Object.defineProperty(Array.prototype, 'removeDuplicatesProperty', { //defining the type and name of the property
    enumerable: false,
    configurable: false,
    writable: false,
    value: function() {
        var arr = this.concat(); // get the input array
        //create the first cycle of the loop starting from element 0 or n
        for(var i=0; i<arr.length; ++i) {
            //create the second cycle of the loop from element n+1
            for(var j=i+1; j<arr.length; ++j) {
                //if the two elements are equal , then they are duplicate
                if(arr[i] === arr[j]) {
                    arr.splice(j, 1); //remove the duplicated element 
                }
            }
        }
        return arr;
    }
});

console.log("Merged arrayC > "+arrayC);
console.log("Removing duplicates using removeDuplicatesProperty > "+arrayC.removeDuplicatesProperty() );

Lo-Dash または Underscore.js を使用してマージし、一意の値のみを保持する

2つ以上の配列からユニークな値の新しい配列を取得して外部ファイルを利用することが目的であれば、Lo-Dash ライブラリを利用することができます。

まず、HTML テンプレート内の Cloudflare CDN を使ってライブラリをインポートする必要があります。

<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

そして、ライブラリのようなものを使用します。

arrayC = _.union(arrayA, arrayB);

例:

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];

console.log('Array A > ' + arrayA);
console.log('Array B > ' + arrayB);

// merging arrayA and arrayB keeping only unique values using Lo-Dash library
//  don't forget to import the script using <script
//  src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.15/lodash.min.js"></script>

console.log(
    'Merging arrayA and arrayB keeping only unique values using Lo-Dash Lib. > ' +
    _.union(arrayA, arrayB));

ECMAScript 6 の Set を使ったマージとユニークな値のみの保持

ECMAScript 6 が使えて、ターゲットが複数の配列のユニークな値だけであれば、Set は非常に良い選択肢となります。

以下の例のように spread 構文を使って使うことができます。

arrayC = [...new Set([...arrayA, ...arrayB])];

あるいは、次のように使うこともできます。

arrayC = Array.from(new Set(arrayA.concat(arrayB)));

例:

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];

console.log('Array A > ' + arrayA);
console.log('Array B > ' + arrayB);

// merging arrayA and arrayB keeping unique values using Set in ECMAScript 6

console.log(
    'Merging arrayA and arrayB keeping only unique values using Set > ' +
    Array.from(new Set(arrayA.concat(arrayB))));

console.log(
    'Merging arrayA and arrayB keeping only unique values using Set with spread syntax > ' +
    [...new Set([...arrayA, ...arrayB])]);

O(n) だけの複雑さで for ループと Dictionary を使用して重複しない値をマージする

2つの配列をマージして重複した値を持たずに結果を得るもう一つの方法は、JavaScriptDictionary の考え方を利用することです。

function mergeAndGetUnique(arrayA, arrayB) {
  var hash = {};
  var x;

  for (x = 0; i < arrayA.length; i++) {
    hash[arrayA[i]] = true;
  }
  for (x = 0; i < arrayB.length; i++) {
    hash[arrayB[i]] = true;
  }
  return Object.keys(hash);
}

そうすれば、このような関数を使用することができます。

arrayC = mergeAndGetUnique(arrayA, arrayB);

var arrayA = ['Java', 'JavaScript'];
var arrayB = ['C#', 'PHP', 'Java'];
var arrayC;

console.log("Array A > "+arrayA);
console.log("Array B > "+arrayB);

arrayC = arrayA.concat(arrayB);

//merging arrayA and arrayB keeping unique values using dictionary with O(n) complexity

function mergeAndGetUnique(arrayA, arrayB) {
  var hash = {};
  var x;
  
  for (x = 0; x < arrayA.length; x++) {
    hash[arrayA[x]] = true;
  }
  for (x = 0; x < arrayB.length; x++) {
    hash[arrayB[x]] = true;
  }
  return Object.keys(hash);
}

console.log("Merging arrayA and arrayB keeping only unique values using Set with spread syntax > "+ mergeAndGetUnique(arrayA, arrayB) );

関連記事 - Java Array