🍒
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 ← 正しくユニーク処理される
仕組み
-
users.map(u => [u.id, u])
で、各オブジェクトを[id, オブジェクト]
の形式に変換 -
new Map()
で、同じキー(id)を持つ要素は上書きされる -
.values()
でオブジェクトのみを取り出し、スプレッド構文で配列に変換
この方法により、IDベースでのユニーク処理がワンライナーで実現できます。
注意事項
この方法は「IDベースのユニーク処理」であり、オブジェクト全体の完全一致を判定するものではありません。
Discussion