【JavaScript】オブジェクトの配列から重複している値が存在する場合は取り除いて新しい配列を返す
投稿日:2019年11月24日
オブジェクトの配列をマージした時に重複しているオブジェクトが存在していた。
重複している値を持つオブジェクトを配列から取り除いて新しい配列を返したい事があったのでメモ。
サンプルコードを2つ載せますが、どちらでも同じ結果が出ます。
IE11でも使えるサンプル(Babel + polyfill 未使用を想定)
// 重複したオブジェクトを持つ配列
const items = [
{ id: 1, name: '一郎' },
{ id: 2, name: '二郎' },
{ id: 3, name: '三郎' },
{ id: 1, name: '一郎' },
{ id: 4, name: '四郎' },
{ id: 2, name: '二郎' }
];
// IE11でも使える(Babel + polyfill 未使用)
function filterUniqueItemsById (array) {
// idを集約した配列を作成
const itemIds = array.map(function(item) {
return item.id;
});
//
return array.filter(function(item, index) {
return itemIds.indexOf(item.id) === index;
});
}
const uniqueItems = filterUniqueItemsById(items);
console.log(uniqueItems);
// => [ {id: 1, name: "一郎"}, {id: 2, name: "二郎"}, {id: 3, name: "三郎"}, {id: 4, name: "四郎"} ]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
解説
filterUniqueItemsById
関数でやっていることは、最初に重複したオブジェクトを持つ配列から、要素のidだけを集約した配列をmap関数を使って作成しています。
続いて、元となる配列(items
)を filter
のコールバックに渡される各要素のidで、idを集約した配列(itemIds
)から indexOf
を使って最初に見つかった要素のみを返します。
その結果、重複が削除された新しい配列が作成されます。
Babel + polyfill を使っている想定のサンプルコード
// 重複したオブジェクトを持つ配列
const items = [
{ id: 1, name: '一郎' },
{ id: 2, name: '二郎' },
{ id: 3, name: '三郎' },
{ id: 1, name: '一郎' },
{ id: 4, name: '四郎' },
{ id: 2, name: '二郎' }
];
const uniqueItemUseES2015 = items.filter((item, index, array) => {
return array.findIndex(item2 => item.id === item2.id) === index;
});
console.log(uniqueItemUseES2015);
// => [ {id: 1, name: "一郎"}, {id: 2, name: "二郎"}, {id: 3, name: "三郎"}, {id: 4, name: "四郎"} ]
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
解説
Babel + polyfill を使うと ES2016の構文が使えるので findIndex
も使えるようになります。
filter
のコールバックに渡される第3引数(この場合items自身)を使って findIndex
のコールバックの引数で渡される要素のidを検索します。
findIndex
はコールバックのテストを満たした場合に配列内のインデックスを返します。
filter
の第2引数のindexを使って findIndex
の返り値と比較し、最初に見つかった要素のみを返します。
その結果、先程のサンプルと同じ用に重複が削除された新しい配列が作成されます。