5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【2021年6月版】JSのArray.reduceとMapで、Object Arrayを簡単にユニークにする

Posted at

JavaScript, TypeScriptで"オブジェクトの配列"を"簡単に"ユニークにしたい。

こちら↓

const arr = [
   { id:"a0", propA: "A0-propA", propB: "A0-propB", ... },
   { id:"a1", propA: "A1-propA", propB: "A1-propB", ... },
   { id:"b0", propA: "B0-propA", propB: "B0-propB", ... },
   { id:"a0", propA: "A0-propA", propB: "A0@propB", ... },
...
];

// シンプルに要素をユニークにする
const uniq_arr_1 = [... arr.reduce((map, a) => map.set(a.id, a), new Map()).values()];
// 要素をユニークにし、変換もする
const uniq_arr_2 = [... arr.reduce((map, a) => map.set(a.id, { id: a.id, value : a.propA, desc: a.propB}), new Map()).values()];

解説

JSやTSで Object Array を distinct したい。オブジェクトの配列要素を特定のプロパティ、メンバで一意にしたい。。。単にArrayをUniqueにする方法でサクッと調べてみるとSetを使う方法が出てきますが、Setでは要素の等価性、同一性の評価がカスタマイズできないので文字列や数値のような"プリミティブ"な要素の配列にしか使えません。。forやforeachで頑張ればできるのですが、できるだけ"簡単に"やりたい、というわけです。

というわけで、Array.reduceMapを使って、Mapのキーに特定のメンバーを指定することで、配列の要素を一意にし、その後 Map.values()とスプレッド構文でArrayに戻しております。
ミソはArray.reduceの第2引数で初期値にnew Map()を渡すこと、そしてMap.setで要素を追加している箇所、そしてMap.valuesです。
Map.setは戻り値がMapなので、Map.setしただけでそのまま暗黙のreturn mapが出来ております。
また、Map.values()とスプレッド構文で簡単にArrayに戻すことが出来ています。

というわけでなかなか悩ましいObject Arrayを一意にする方法ですが、Array.reduceMapを駆使して簡単にできました。

5
1
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?