解説
Setで同じidのオブジェクトが残る?値と参照で重複を比べよう
Setはオブジェクトのidを自動比較しない。文字列・数値・別々のオブジェクト・同じ参照を、小さな作例で比べて一意化の条件を整理。

配列をSetへ入れたのに、同じidを持つオブジェクトが二つ残った。Setは、その中のidという項目を自動で選んで比較する仕組みではないよ。
今回は小さな架空の配列で、値と参照の違いを見る。配列とオブジェクトの基本を知っている人向けに、ブラウザで操作できる作例も用意したよ。
同じプリミティブ値は一つになる
console.log([...new Set(["a", "a", "b"])]);
// ["a", "b"]
console.log([...new Set([1, "1", 1])]);
// [1, "1"]
Setは一意な値の集まりを作る。文字列のaを繰り返した場合は一つになるけれど、数値1と文字列"1"を、見た目が似ているから同じと扱うわけではない。
別々に作ったオブジェクトは別の要素
const first = { id: 1 };
const second = { id: 1 };
console.log(new Set([first, second]).size); // 2
console.log(first === second); // false
二つの中身は似ていても、別々に作ったオブジェクト。それぞれが指す参照は異なるため、Setでは二つ残る。
idだけで比べたい、すべての項目で比べたい、文字の表記をそろえて比べたい、という業務の条件を、Setが勝手に決めてくれるわけではないよ。
同じ参照を二回渡した場合
const same = { id: 1 };
console.log(new Set([same, same]).size); // 1
こちらは同じオブジェクトを二回渡しているので、一つになる。JSONで表示した見た目が同じでも、元の参照が違うかどうかで結果が変わるんだ。
作例で四つを比べよう
| 入力 | Setの要素数 |
|---|---|
| 同じ文字列を含む配列 | 2 |
| 数値1と文字列1を含む配列 | 2 |
| idが同じでも別々のオブジェクト | 2 |
| 同じオブジェクトの参照を二回 | 1 |
作例は、入力、Setから戻した配列、要素数、先頭二つの===を表示する。「最初から試す」で文字列の例へ戻れるよ。
JSON表示は参照の違いを表さないので、同じ文字に見えることだけで判断しないようにしよう。
idで重複を整理するなら、採用ルールが必要
同じidで、名前など別の項目が違う行があったら、先頭を採るのか、最後を採るのか、矛盾として保留するのかを決める必要がある。
キーだけをSetへ入れて既出か確認する設計はできるけれど、それは「どの項目をキーにするか」を自分で決めた処理。元の行を消す前に、衝突した記録を確認したいね。
動かしてみよう:値と参照の重複
四つの配列でSetの件数を比べ、同じidと同じ参照を分けて見よう。

みんなのコメント 0
感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。
最初のコメントをどうぞ。