Javascript で配列内の重複した要素を1つにまとめる

  • Javascript

配列内に重複した要素がある場合、同じものをマージして1つにするやり方です。

値、文字列の重複をまとめる

new Set()を使うと、配列内に重複している値、数値などを簡単に重複を1つにまとめることができます。
https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Global_Objects/Set

const numbers = [1,2,54,3,4,6,3,3,54,10];
const numbersFiltered = new Set(numbers);
console.log([...numbersFiltered]) // [1, 2, 54, 3, 4, 6, 10]

new Set()で生成したもの(ここでいうnumbersFiltered)を出力しようとすると Set オブジェクトになってしまっているので、配列として扱いたい場合はスプレッド演算子(…)で抜き出せます。

オブジェクトの重複をまとめる

オブジェクトの重複は Set ではまとめられません。filter と findIndex を組み合わせて使うと良いみたいです。

例:data を重複フィルタリングする

const data = [ ...何かしらのオブジェクト ];
const dataFiltered = data.filter((element, index, self) => self.findIndex(
  (dataElement) => dataElement.id === element.id ) === index
);

dataはオブジェクトの配列とします。このオブジェクトの中身のidが同じものは重複と見なし、2つ目は除外する例です。

  • array.filter() … true なら配列に追加する
  • array.findIndex() … true ならその要素のインデックス番号を返す

filter()は配列の中身を一つずつ取り出して、何らかの条件が true であれば、配列に追加していき、フィルタリングされた配列を返します。なので常に true を返すと、最初とまったく同じ配列が出来上がるだけで意味はありません。

findIndex()は配列の中身を一つずつ取り出して、何らかの条件が true であれば、その要素のインデックス番号を返します。もし true にならなければ、-1が返るというものです。

なので、上記でやっていることの流れとしては

  1. filter()で重複をまとめたい配列をフィルタリング
  2. filter()の第三引数 self (フィルタリングをしようとしてる配列が入る。例でいうとdata)に対してfindIndex()をかける
  3. data に入ってる id と、filter()で順番に取り出している element の id が等しければ、data に入っている index 番号を返す(合致した一番最初の要素
  4. その index 番号がfilter()で順番に取り出している index 番号と等しければ、最終的に返す配列に追加する

findIndex() は合致した一番最初の要素を返すのがキモです。
例えば、配列内の 2番目、5番目、10 番目のオブジェクトの id が同じだった場合、findIndex()は2番目のインデックス番号を返してきます。

なので、2番目 === index となり、index が 2番目の時のみ true、新しい配列に加えられます。5番目と10番目はスルーされ、重複しているオブジェクトは一つだけになるという戦法です。

正直自分では考え付きませんでした。すごいです。。