2
0

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 1 year has passed since last update.

JavaScript コレクションで重複データ除去

Posted at

JavaScriptで重複データを除去するケースがあるとおもうので、書いてみた。

そもそも重複したデータを追加したくない

Setを使えばOK。

const array1 = new Set();

array1.add('A');
array1.add('B');
array1.add('A');  // 重複
array1.add('C');

for (let val of array1.values()) {
  console.log(val);
}
実行結果
A
B
C

重複値「A」が追加されていない!!

オブジェクト型のデータも重複して登録したくない

標準のSet.addではオブジェクトの重複チェックはないので、ちょっと改造が必要です。

const array1 = new Set();

// 既存のaddメソッド上書き
array1.add = function(obj) {
  for (let o of this) {
    if (o.id === obj.id) {
      //存在済み
      return;
    }
  }
  Set.prototype.add.call(this, obj); // もともとのSet.addをコール
}

array1.add({id: 'A', name: 'たろう'});
array1.add({id: 'B', name: 'じろう'});
array1.add({id: 'C', name: 'はなこ'});
array1.add({id: 'B', name: '次郎'}); // IDが重複

for (let val of array1.values()) {
  console.log(val);
}
実行結果
{id: 'A', name: 'たろう'}
{id: 'B', name: 'じろう'}
{id: 'C', name: 'はなこ'}

ID:B の重複データが登録されていない!!

重複値を除去したい

既存の配列の重複値を除去する場合もSetを使えばOK。

const array1 = ['A', 'B', 'C', 'D', 'A', 'C'];

const uniqueArray = new Set(array1).values();

for (let val of uniqueArray) {
  console.log(val);
}
実行結果
A
B
C
D

オブジェクト型の重複値を除去したい

既存のオブジェクト型の配列の重複値を除去する場合は、ちょっと工夫します。

const users = [
{id: 'A', name: 'たろう'},
{id: 'B', name: 'じろう'},
{id: 'C', name: 'はなこ'},
{id: 'B', name: '次郎'}, // IDが重複
];

const uniqueArray = new Map(users.map((user) => [user.id, user])).values();

for (let val of uniqueArray) {
  console.log(val);
}
実行結果
{id: 'A', name: 'たろう'}
{id: 'B', name: 'じろう'}
{id: 'C', name: 'はなこ'}

りくつ

const uniqueArray = new Map(users.map((user) => [user.id, user])).values();

これで、なんで重複除去できるんだ??
ですが、1つづ分解してみます。

まず
usersの配列から新しい値の配列を作成します。

users.map((user) => [user.id, user])
実行結果
[
  ['A', {id: 'A', name: 'たろう'}]
  ['B', {id: 'B', name: 'じろう'}]
  ['C', {id: 'C', name: 'はなこ'}]
  ['B', {id: 'B', name: '次郎'}]
]

次に
この結果からMapオブジェクトを作成します。
Mapオブジェクトのコンストラクタは

new Map([[キー1, 要素1], [キー2, 要素2]])

なので、

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

は、こんなイメージになります。


new Map(
[
  ['A', {id: 'A', name: 'たろう'}]
  ['B', {id: 'B', name: 'じろう'}]
  ['C', {id: 'C', name: 'はなこ'}]
  ['B', {id: 'B', name: '次郎'}]
]
)

この時、キーの値「B」の値が重複しているのでMapは

  ['A', {id: 'A', name: 'たろう'}]
  ['B', {id: 'B', name: 'じろう'}]
  ['C', {id: 'C', name: 'はなこ'}]

になり、この結果、重複が無くなる、っていうことです。

補足

上記の検証では、valuesメソッドを使用してますが、
このメソッドの戻り値はIterator(反復処理)オブジェクトが戻ってくるので
forとかでグルグル回せますがが、push等の配列処理は出来ないので注意して下さい。

もし、重複除去後に要素追加などをするのであれば

const uniqueArray = Array.from(new Set(array1).values());
const uniqueArray = Array.from(new Map(users.map((user) => [user.id, user])).values());

のようにArrayオブジェクトにしましょう。

以上です。

2
0
0

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
2
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?