🍒

JavaScriptでオブジェクト配列のユニーク処理はSetではできません。

に公開

問題:Setによるユニーク処理が期待通りに動かない

配列のユニーク処理といえばSetを使ったワンライナーが定番ですが、オブジェクト配列では期待通りに動きません。

const users = [
  {id: 1, name: "田中"},
  {id: 2, name: "山田"},
  {id: 1, name: "田中"}
];
const uniqueUsersWithSet = [...new Set(users)];
console.log(uniqueUsersWithSet.length); // 3 ← 期待は2なのに...

原因:オブジェクトの比較は参照ベース

なぜSetでは動かないのでしょうか?
JavaScriptでは、オブジェクトの比較が参照ベースで行われるためです。

const obj1 = {id: 1};
const obj2 = {id: 1};
console.log(obj1 === obj2); // false

同じ内容のオブジェクトでも、===比較では「別物」として扱われます。Setは内部的にこの比較を使用するため、内容が同じオブジェクトでも重複として認識されません。

解決策:Mapを使ったワンライナー

オブジェクト配列のユニーク処理には、Mapを使用します。

const uniqueUsersWithMap = [...new Map(users.map(u => [u.id, u])).values()];
console.log(uniqueUsersWithMap.length); // 2 ← 正しくユニーク処理される

仕組み

  1. users.map(u => [u.id, u]) で、各オブジェクトを [id, オブジェクト] の形式に変換
  2. new Map() で、同じキー(id)を持つ要素は上書きされる
  3. .values() でオブジェクトのみを取り出し、スプレッド構文で配列に変換

この方法により、IDベースでのユニーク処理がワンライナーで実現できます。

注意事項

この方法は「IDベースのユニーク処理」であり、オブジェクト全体の完全一致を判定するものではありません。

株式会社THIRD エンジニアブログ

Discussion