JavaScriptのset (および複数)を使用した、ユニークでマージされた配列の作成


Blog header image for creating unique merged arrays using JavaScript's Set
画像シーン:あなたは2つ以上の(または複数の)類似の配列を持っている、それぞれが重複したデータを含む.JavaScriptを使用して、ユニークな値だけを含む1つの配列に2つのマージを行うにはどうすればよいですか?
さて、それがわかるように、かなりの数の方法があります.
以下のすべてのセクションでは、以下の2つの配列を使用します.
const arr1 = [1,2,3,4,5,6];
const arr2 = [1,3,4,7,8,9];
我々は、この記事のすべての派手な矢印機能を使用しますあなたならば.

何かについては、またはエレガントなスプレッド構文?


確かに、2つ以上の配列をマージできますconcat() メソッドまたはshiny ES6/ES2015 spread syntax .
arr1.concat(arr2)
// OR
[...arr1, ...arr2] // this is functionally the same as concat

// logging to the console, both the above will produce:
// [1, 2, 3, 4, 5, 6, 1, 3, 4, 7, 8, 9]
これらの両方の方法は大きいです:彼らはコンパクトで、効率的で、2つ以上の配列を合併する際に本当に単純な仕事をします.しかし、実際には、前の配列の最後に1つの配列を追加するだけです.
あなたが本当にユニークな値の1つの配列を持っていることを気にするならば、我々は何かをためさなければならないつもりです.

1、旧式の、しかし、信頼できるforeachループ


ああ、古い友人の慰めのような何もforEach() 配列メソッド.あなたが見ることができるようにMDN web docs on forEach 配列の各項目の上の単純なループです.あなたはそれを関数を渡し、何をする必要があります.
それは新しい配列を返さないか、既存の配列のデータを変えません、それはちょうど問題の配列の項目からアイテムまで移動します.そして、コールバック機能で必要なものは何でもします.
つの配列を単一のユニークな出力に結合するために使用するには、次のようにします.
let combinedArr = [];

arr1.forEach(value => {
  if(!arr2.includes(value)) {
    combinedArr.push(value);
  }
});

combinedArr = combinedArr.concat(arr2);

// outputs > [2, 5, 6, 1, 3, 4, 7, 8, 9]
これは良い.1つの配列の希望の結果を得て、一意の値のセットを完備します.
この例では、最初の配列をとります.arr1 を返します.arr2 . ユニークであれば、最後の配列に加えます.combinedArr . 一度forEach が完了すると、我々は全体のコンテンツを追加arr2 onto the end of combinedArr なぜなら、そこにあるすべての価値がユニークであることを知っているからです.
プラス側forEach 上記のような単純な何かをするだけであるならば、プロセッサ(バベルのような)を必要とすることなく、箱から古いブラウザーとのより多くの互換性を持ちます、そして、それは十分にコンパクトです.
下向きは、それがよりエレガントな解決であるために成長することができるということです--特に複数の配列のために-そして、それは最終的な配列にどんな順序の注文も提供しません;たぶん、大きなことはありませんが、あなたのニーズに問題がある場合は、上に移動する必要があります.

2、Sinierフィルタアプローチ


ES 5/ECMAScript 5仕様から古いブラウザーと互換性を持つもう一つの配列メソッドは、便利ですfilter() . あなたはread more on the MDN docs on the filter method , しかし、それは同様の方法で動作しますforEach , 配列の各項目をループします.しかし、今回は、最終的な配列の項目を保持するか、または削除する(すなわち、それをフィルタアウトする)ようにtrue/false値を返すコールバック関数を実行します.
それはまた、元の配列を変更しない間、それは新しい、フィルタリングされた1つを返します.
ここでは、前の例での実装の変更について説明しますfilter :
arr1.concat(arr2.filter(value => !arr1.includes(value)));

// outputs > [1, 2, 3, 4, 5, 6, 7, 8, 9]
我々は、同様の操作を実行しているforEach つは、ここでは、我々はフィルタリングarr2 onto arr1 . フィルタの間、任意の値をarr2 それは現在arr1 使用includes メソッド.
The filter アプローチは、その簡潔な構文で多くのネーターを探している利点があります.また、複数の配列のためにこのアプローチを繰り返すとき、それは少しより明確に見えます、しかし、あなたが多くをしているならば、それは少し乱雑に見え始めます.

3、別の何かを減らすために使用


あなたが本当に空想を得たいならば、あなたは使うことができますarray.reduce() . 見るthe MDN docs on reduce , 彼らは、それがメソッドなどの複数の組み合わせを使用するよりも、より効率的なアプローチであることができます言及filter and map .
しかしながら、私たちの目的のために、以下のようにreduceを使います.
let uniqueArr = arr1.concat(arr2).reduce(
  (accumulator, currentValue) => {
      if(!accumulator.includes(currentValue)) {
        accumulator.push(currentValue);
      }

      return accumulator;
  }, []
);

// outputs > [1, 2, 3, 4, 5, 6, 7, 8, 9]
我々は、連結されたスターター配列を持っていますarr1 and arr2 ) それから私達は走るreduce を参照してください.reduceは2つの引数、コールバック関数と初期値を受け入れます.コールバック関数は2つの引数を受け付けます.
私たちが使っている引数と何をしますか
  • コールバック>アキュムレータ-コールバック関数のreturn文の集合で終わる配列.
  • callback>current value -ループ内の現在位置の配列の現在の項目を返します.
  • reduce >初期値-空の配列を渡します([] ) ここで、還元器は、ターゲット配列の位置0で開始されます.指定されなかった場合は1から開始します.
  • The reduce メソッドはグリップを得るために少し厄介なことができますが、一度そこに着くと、それはあなたのベルトでは、配列を操作すると確かに特定のアプリケーションでは本当に便利な場所を持って持っている強力なツールです.あなたはread the MDN docs on reduce for more use cases .
    それは少し醜いに見えるが、それは非常にパフォーマンスと効率的なアプローチすることができます.それは我々の出力をソートするボーナスもあります.
    また、完全なセットで働くことができることのスーパーボーナスを持っています.したがって、複数の配列を一緒にmushする必要がある場合は、最初にそれらを連結して実行することができますreduce 全体のロットで:より長い見て、より効率的に見てニッカー.

    スーパーファンシーセット法


    さて、あなたが光沢のあるES 6/ECMA 2015タイプの1つであるならば、あなたはスーパーファンシーを利用することができますSet オブジェクト.もう一回.referencing the MDN docs on Set , Set 値のコレクションとしてプリミティブ型を格納できるオブジェクトです.
    それは配列オブジェクトに多くの類似点を提供します、しかし、最大の利点はセットがユニークな値を含むかもしれないということです!さらに新しいものを作るときSet それは親切に任意の重複を削除することによって私たちのための作業を-甘い!
    見てみましょう
    const mySet = new Set([
      ...arr1,
      ...arr2
    ]);
    
    // outputs > [1, 2, 3, 4, 5, 6, 7, 8, 9]
    
    今、どのように清潔で簡単ですか?特に、私たちの2つの(またはより多くの)配列の連結を広げるために広げられた構文と結合するとき.
    これは他の方法に比べて3つの大きな利点を提供します.
  • これは、ユニークな値のマージされた配列を作成するのは、はるかにきれいで、ターサーアプローチを提供しています.
  • それはより良いスケール.どのように簡単に配列の別の一握りを建設者に加えることができて、コードがちょうどきちんとしたように見えるのを見ることができます.
  • Set あなたのためのハードワークと重複を削除します.
  • 最大の逆さまはセットが速く燃えていて、ユニークである必要がある配列を結合する私の試みへの私の試み方法です.
    もちろん、下側はSet 新しい言語機能で、BabelやPolyFillを使用しない限り古いブラウザではサポートされません.また、余分なステップに移動し、新しい結果を変換する必要がありますてSet を配列に設定するか、そうでなければイテレブルなものにして、それをもっと行うことができます.
    しかし、これは大きな負担ではありません.
    const newArr = Array.from(mySet);
    // OR
    const newArr = [...mySet];
    

    パフォーマンスに関するノート


    人々は様々なJavaScriptのもののパフォーマンスにハングアップするようになります.Indead、あなたがスタックオーバーフローのまわりで速いNoseyを持っているならば、あなたはたくさんの' um 'を見つけますメソッドAがメソッドBより速く、またはより効率的である理由を説明するのが好きで、「間違った」ものを使用するためにあなたを育てるタイプ.
    上の例を使用すると、ブラウザのデバッグツールを使用してパフォーマンスをテストすることができます、そして、あなたはそれらがすべて同じで、すなわち1 - 2 ms範囲内のどこかに入ってくるのを見つけるでしょう.しかしながら、これはブラウザー操作キャッシュのようなものと我々がここで合併しているアレイの全くの分のスケールのために激しく変化します.基本的に、彼らはパフォーマンスの時間に意味のある影響を本当に与えるために小さすぎる.
    しかし、それがパフォーマンスになると、物事のアプリケーションの周りに引数がたくさんあります.たとえば、公共の情報サイトをロードしたり、管理コンソールのような捕虜の聴衆でアプリケーションを提供していますか?
    パフォーマンスは重要ですが、重要ではありませんが、ロード時間から1ミリ秒の分を節約するので、あなたのコードにパフォーマンス狩猟斧のいくつかの並べ替えを取ることに圧力をかけないでください.
    アプリケーションのアプリケーション、ユーザー、およびコードの生態系の透明性と保守性を考慮してください.
    と言った.

    科学を話しましょう!


    OK、OK、ハードデータが欲しい.さて、ここに行く.
    いくつかの大きな配列でこれらのメソッドのパフォーマンスをテストし、様々な時間をチェックして、私たちの元の配列をarr1 and arr2 ) それぞれの整数値をそれぞれ.
    リストされた操作の各々を実行した後に、関連した時間が、ここにあります:
  • forEach > 102 ms
  • filter > 124 ms
  • reduce > 223 MS
  • Set > 7 ms
  • 我々の謙虚forEach 実際にCLUNKIERと比較して超高速ですreduce しかし、どれも作品の主人公として演じることはない.Set .