JavaScript 逆引き集 | 配列をユニークに(オブジェクトキーで)

JavaScript JavaScript
スポンサーリンク
スポンサーリンク

「オブジェクトのキー」を使ってユニークにする発想

Object.values(_.keyBy(arr, 'id')) は、「オブジェクト配列から、特定のキー(ここでは id)を基準に重複を取り除く」ためのテクニックです。 単なる数値配列なら new Set で重複除去できますが、オブジェクト配列になると「どのプロパティを基準にユニークにするか」を決める必要があります。 そのときに使えるのが、lodash の _.keyByObject.values の組み合わせです。

lodash の keyBy がやっていること

_.keyBy(arr, 'id') は、「配列の各要素を、指定したキーを使ってオブジェクトに並べ替える」関数です。

例を見てみます。

const arr = [
  { id: 1, name: "Aki" },
  { id: 2, name: "Mika" },
  { id: 1, name: "Aki (duplicate)" }
];

const keyed = _.keyBy(arr, 'id');

console.log(keyed);
/*
{
  1: { id: 1, name: "Aki (duplicate)" },
  2: { id: 2, name: "Mika" }
}
*/
JavaScript

ここで重要なのは、同じ id のものは、最後に出てきたものが上書きされるという点です。 keyBy は「id をキーにしたオブジェクト」を作るので、 同じキーが複数あれば、最終的にそのキーにはひとつのオブジェクトしか残りません。

つまり、keyBy の時点で 「id ごとに1件だけ」という状態が作られます。 これが「ユニーク化」の核になります。

Object.values で「オブジェクトをまた配列に戻す」

keyBy の結果は「オブジェクト」です。 しかし、最終的に欲しいのは「ユニークなオブジェクトの配列」ですよね。

そこで使うのが Object.values(...) です。

const uniqueArr = Object.values(_.keyBy(arr, 'id'));

console.log(uniqueArr);
/*
[
  { id: 1, name: "Aki (duplicate)" },
  { id: 2, name: "Mika" }
]
*/
JavaScript

Object.values(obj) は、オブジェクトの「値」だけを配列として取り出す関数です。 keyBy で「id ごとに1件だけ」にしたあと、 その「1件ずつ」を配列として取り出すことで、「id を基準にユニークな配列」が完成します。

例題:ユーザー一覧を id でユニークにする

実務でよくあるパターンをイメージしましょう。

const users = [
  { id: 1, name: "Aki" },
  { id: 2, name: "Mika" },
  { id: 1, name: "Aki (from another source)" },
  { id: 3, name: "Ken" }
];

const uniqueUsers = Object.values(_.keyBy(users, 'id'));

console.log(uniqueUsers);
/*
[
  { id: 1, name: "Aki (from another source)" },
  { id: 2, name: "Mika" },
  { id: 3, name: "Ken" }
]
*/
JavaScript

ここで起きていることはこうです。 同じ id を持つユーザーが複数いても、最終的に id: 1 のユーザーはひとりだけになります。 どれが残るかというと、「最後に現れたもの」です。

この「最後のものが勝つ」という挙動は、 「後から取得したデータで上書きしたい」ときに都合が良いことが多いです。

「どのキーでユニークにするか」を自分で選べる強さ

_.keyBy(arr, 'id')'id' の部分は、もちろん他のプロパティにも変えられます。

メールアドレスでユニークにしたければ 'email'。 商品コードでユニークにしたければ 'code'

つまり、「この配列は、このプロパティを基準にユニークにしたい」という意図を、そのままコードに表現できるわけです。 これは Set ではできない、オブジェクト配列ならではのユニーク化の考え方です。

まとめ:Object.values(_.keyBy(arr, 'id')) は「オブジェクト配列をキーでユニークにする定番パターン」

数値や文字列の重複なら new Set で十分ですが、 オブジェクト配列になると「どのプロパティを基準にユニークにするか」を決める必要があります。

その答えのひとつが、 Object.values(_.keyBy(arr, 'id')) という書き方です。

keyBy で「キーごとに1件だけ」にまとめる。 Object.values で「その1件ずつを配列として取り出す」。

この流れを理解できると、 「オブジェクト配列の重複除去」という、ひとつ上のレベルの配列処理が自然に書けるようになります。

タイトルとURLをコピーしました