通常の配列を操作する場合
const arr = [ 'hoge', 'fuga', 'poke', 'wakuteka', 'hoge', 'hoge' ]
今回はこんなデータを使用します
重複データのみ抽出する
const arr2 = arrarr.filter(function (val, idx, arr){
return arr.indexOf(val) === idx && idx !== arr.lastIndexOf(val)
})
// 以下のようになります。
console.log(arr)
// (6) ["hoge", "fuga", "poke", "wakuteka", "hoge", "hoge"]
console.log(arr2)
// ["hoge"]
重複を取り除く
const arr3 = arr.filter(function(val, idx, arr){
return arr.indexOf(val) === idx
})
// 以下のようになります。
console.log(arr)
// (6) ["hoge", "fuga", "poke", "wakuteka", "hoge", "hoge"]
console.log(arr2)
// (4) ["hoge", "fuga", "poke", "wakuteka"]
他以下記事を参考にしてみてください。
本題
ようやく、本題です。
今回は以下のような多次元配列を使用します。
const arr = [
{ id: 1, name: '太郎', money: 3000 },
{ id: 2, name: '次郎', money: 1000 },
{ id: 3, name: '三郎', money: 1200 },
{ id: 2, name: '次郎', money: 500 },
{ id: 1, name: '太郎', money: 1300 },
{ id: 1, name: '太郎', money: 10000 }
]
こんな感じの配列で、idで重複を確認しmoneyを加算させたデータを作りたいとします。
実装
let nonDupArr = arr
let dupArr = []
let dupObj = {}
let dupIdxArr = []
arr.filter((o, i, arr) => {
arr.filter((o2, i2) => {
if (i !== i2 && o.id === o2.id) {
// 重複分を取得
if (!dupIdxArr.includes(o.id)) {
dupObj = {
id: o.id,
name: o.name,
money: o.money + o2.money
}
// 配列に追加
dupArr.push(dupObj)
}
// 重複分のidを配列に追加
dupIdxArr.push(o.id)
}
})
})
// 重複分のidを回して、該当する要素を配列から削除
dupIdxArr.forEach(id => {
let idx = nonDupArr.findIndex(e => e.id === id)
nonDupArr.splice(idx, 1)
})
- まず、重複分を格納する配列と重複分を除いた要素を格納する配列を用意します
-
const
で定義した配列(※以下A配列)をfilterし、更に第三引数で元の配列(※以下A´配列)を更に中でfilterします。 - A配列でfilterした要素のインデックスとA´配列でfilterした要素のインデックスが違う且つ、A配列でfilterした要素のidとA´配列でfilterした要素のidが同じことを確認します。
- 重複して保存されない様に、重複した分の要素のidを専用の配列(以下B配列)に格納し、B配列にA配列からfilterした要素のidをincludesで確認、入っていなければ、新たなオブジェクトとして配列に保存していきます。
→ここまでで重複分の要素を入れた配列が完成です。
- 次に先程保存したB配列をforEachで回します。
- A配列から、findIndexでB配列に保存されているidと重複するidの要素を取得します。
- 取得したオブジェクトをA配列から削除します
→これで重複分を除いた配列の完成です。
まとめ
いかがでしたでしょうか?
配列から完全一致の要素を削除したり、抽出するパターンは往々にしてあると思いますが、重複する要素を更に加工するケースの際是非ご活用ください。
また、より良い記述ご存知の方是非コメントでご教授いただけますと幸いです。