😀

配列内にあるオブジェクトの重複を排除したい

2020/10/06に公開

#ある時
javascriptで配列へ格納していく時に、オブジェクトの重複を削除する必要性が出てきた。

[
 { name:'Apple',jpname:'りんご',price:'5000000000000000'},
 { name:'Orange',jpname:'みかん',price:'200'},
 { name:'Banana', jpname:'バナナ',price:'200'},
],
[
 { name:'Apple',jpname:'りんご',price:'200'},
 { name:'Grape',jpname:'ぶどう',price:'200'},
 { name:'melon', jpname:'メロン',price:'200'},
]

この2つの配列をマージしたいけど、重複して同じオブジェクトがあった場合には排除したい場合など

手法

filterfindIndexなどを用いる方法がありますが、
Mapオブジェクトを用いて重複排除をする処理をやってみましょう。

使用する機能

Array.reduce
Map Object
Array.from

コード

今回の要のコードは以下の通りになります

  const mergearray = [...array1, ...aaray2];

  const resultarray = Array.from(
    mergearray.reduce((map, currentitem) => 
	    map.set(currentitem.text.engname, currentitem),
            new Map()
      ).values()
    );

説明

処理の順番でコードに関する説明を行っていきます。

まず最初に2つの配列を1つにマージします。
この時はまだ単純に2つの配列を1つにするだけです。

  const mergearray = [...array1, ...aaray2];

次にマージした配列でArray.reduceを使い引数内で処理を行っていきます。

    mergearray.reduce((map, currentitem) => 
	   //.....//  ,
            new Map() //初期値としてMap Objectのインスタンスを作成
      ).values()

ここでポイントなのが、Array.reduceinitialValue、最初の初期値で
Map Objectのインスタンスを作成しておくことです。
これにより、Array.reduceのコールバックで呼び出される前回の値を最初から
Map Objectにすることができます。

次に、先程作成したMap Objectsetを用いkeyと現在処理されている配列の要素を追加していきます。

   map.set(currentitem.name, currentitem)

この時、setの第一引数がkeyとなりそれの内容を作っていきます。

   {
     Apple:{...},
     Orange:{...},
     ....
   }

といった具合に作成されていきます。
ここで、もし同じKeyがあった場合は、そのKeyの内容を上書きしていきます。
つまり、同じ内容があった場合に重複を上書きしていくことで排除していくという処理になります。

最後に、作成したMapオブジェクトより配列を生成します。

  const resultarray = Array.from( ... );

Array.fromの引数に入るイテレータやオブジェクトから新しい配列のインスタンスを作成します。
今回はMapオブジェクトからを経由し、配列で欲しいためこのArray.from()を利用します。

これで重複が排除された1つの配列を作成することができました。

おわりに

単純な配列の重複を排除するのであれば、Setオブジェクトを使ってやっていくのですが、
チョット複雑なオブジェクトを持った配列の重複削除となると、Setではうまく動作しないので、
ちょっとした工夫が必要となります。

今回は、それをMapオブジェクトを使ってやってみようという内容でした!

Discussion