10
Help us understand the problem. What are the problem?

posted at

updated at

【Javascript】オブジェクトの配列をuniqueにする(重複を削除する)ときはfilterではなくMapオブジェクトを使う

はじめに

単純な配列は以下のようにSetを使うと重複を削除できるというのがよく知られてます。

const numbers = new Set([1, 2, 1, 1])

const uniqueNumbers= Array.from(numbers)
//uniqueNumbers は [1, 2]

以下のようなオブジェクトの配列の重複を削除する方法はあまり紹介されていなかったのでメモとして書きます。

const users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 1, "name": "Alice"}, {"id": 1, "name": "Alice"}]
// [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}] にしたい

Mapを使って重複を削除する

データ量が多いときはArray.prototype.filter()ではなくMapを使いましょう。(理由は後述)

MapArray.prototype.map()ではなくMapのことです。

結論から言うとコードは以下のようになります。

const users = [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}, {"id": 1, "name": "Alice"}, {"id": 1, "name": "Alice"}]

const uniqueUsers = Array.from(
  new Map(users.map((user) => [user.id, user])).values()
);
// uniqueUsers は [{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}]

Mapについて詳しくは他の記事で紹介されているので、ここでは簡単に説明します。
Mapkey-value型のオブジェクトで、任意の値をkeyとして使用することができます。

先程のコードだと、useridがkeyでuserがvalueとなるようにMapを作成します。
Mapでは同じkeyに違う値を設定できないので、Mapを作成する際に重複が削除されます。

const userMap = new Map(users.map((user) => [user.id, user]))

// 以下のようなイメージになります(厳密にはこのようなオブジェクトではないです。)
// {
//   1: {"id": 1, "name": "Alice"},
//   2: {"id": 2, "name": "Bob"}
// }

Mapを作成したらMap.prototype.values()でvalueのみを抽出して、Array.from()で配列に変換したら終了です。

Map.prototype.values()Iteratorオブジェクトを返すのでArray.from()で変換が必要です。

filterを使わない理由

以下のような方法でも重複を削除することが可能です。
findIndexで最初のインデックスを取得してfilterする(1個目だけ採用して重複を削除する)シンプルな書き方です。
標準的な関数を使っているので読みやすいかもしれません。

const uniqueUsers = users.filter(
  (element, index, self) => self.findIndex((e) => e.id === element.id) === index
);

filterを使わずにMapを使いましょう。」と言いましたが、実は、「要素数が小さい配列を」「頻繁に(多数)処理する」という前提がある場合には、filterを使ったほうが早いです。(詳細は以下の記事を参考にしてください。)

個人的にはデータ量が増えたときにも対応できるのでMapで書いておいたほうがいいかなと思ってます。

まとめ

Mapを使ってオブジェクトの配列の重複を削除する方法を紹介しました。

タイトル詐欺みたいですが、処理するデータ量が少ないときはfilterのほうがいいです。
でも、個人的にはデータ量が増えたときのためにMapで書いておいたほうがいいかなと思ってます。

なにかのお役に立てれば幸いです。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Sign upLogin
10
Help us understand the problem. What are the problem?