配列内にあるオブジェクトの重複を排除したい
#ある時
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つの配列をマージしたいけど、重複して同じオブジェクトがあった場合には排除したい場合など
手法
filter
やfindIndex
などを用いる方法がありますが、
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.reduce
のinitialValue
、最初の初期値で
Map Object
のインスタンスを作成しておくことです。
これにより、Array.reduce
のコールバックで呼び出される前回の値を最初から
Map Object
にすることができます。
次に、先程作成したMap Object
へset
を用い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