71
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

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

Last updated at Posted at 2021-09-21

はじめに

単純な配列は以下のように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で書いておいたほうがいいかなと思ってます。

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

71
37
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
37

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?