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オブジェクトにしましょう。
以上です。