DESIGN / CODE / INFRA / AI

解説

Setで同じidのオブジェクトが残る?値と参照で重複を比べよう

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

Setで同じidのオブジェクトが残る?値と参照で重複を比べよう
保存リストを見る →
この記事の道しるべ 5項目

配列を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へ入れて既出か確認する設計はできるけれど、それは「どの項目をキーにするか」を自分で決めた処理。元の行を消す前に、衝突した記録を確認したいね。

編集部ではNode.jsとChromiumで四つの例、数値と文字列、参照とリセットを確認した。Setのあらゆる値の比較を同じ例で網羅したわけではないよ。共有される参照は浅いコピー、データの役割はIDと表示名の重複も参考になるね。

動かしてみよう:値と参照の重複

四つの配列でSetの件数を比べ、同じidと同じ参照を分けて見よう。

参考・出典

公開と変更の記録
  • :初回公開

日時は日本時間です。記載のある変更は、確認できた編集記録に基づきます。更新日の違いだけから変更内容を推測して載せることはありません。

更新・訂正の方針 →

みんなのコメント 0

感想や、試してみたことを聞かせてね。コメント・返信は承認後に公開されます。

最初のコメントをどうぞ。