从类似
的数组中 [{'name': 'a', 'val': 1}, {'name': 'b', 'val': 2}, {'name': 'a', 'val': 3}]
我想去:
[{ name: 'b', val: 2 }, { name: 'a', val: 3 }]
。
例如,可以通过以下方式实现:
arrOut = _.uniqBy(arrIn.reverse(), 'name').reverse();
但是我正在寻找一种更快/更清洁的方法,而无需两次反转整个数组。
答案 0 :(得分:2)
这是一个想法:在数组上迭代两次。第一次计算每个名称的出现次数,第二次如果元素的计数不为1,则过滤掉元素。
示例:
const arrIn = [{'name': 'a', 'val': 1}, {'name': 'b', 'val': 2}, {'name': 'a', 'val': 3}];
const counter = Object.create(null);
for (const element of arrIn) {
counter[element.name] = (counter[element.name] || 0) + 1;
}
const arrOut = arrIn.filter(element => counter[element.name]-- === 1);
console.log(arrOut);
另一种方法是以相反的顺序遍历数组,跟踪您所看到的名称并在结果上调用.reverse
:
const arrIn = [{'name': 'a', 'val': 1}, {'name': 'b', 'val': 2}, {'name': 'a', 'val': 3}];
const arrOut = [];
const seen = new Set();
for (let i = arrIn.length; i--;) {
if (!seen.has(arrIn[i].name)) {
arrOut.push(arrIn[i]);
seen.add(arrIn[i].name);
}
}
console.log(arrOut.reverse());
答案 1 :(得分:0)
尝试使用shift()
此方法删除第一个数组元素
答案 2 :(得分:0)
如果应保留原始顺序,一种替代方法是将Array.filter()与Array.some()结合使用。这是我尝试保留元素的原始顺序:
let input = [
{'name': 'a', 'val': 1},
{'name': 'b', 'val': 2},
{'name': 'a', 'val': 3}
];
let res = input.filter(
({name, val}, idx, arr) => !arr.some((o, j) => o.name === name && j > idx)
);
console.log(res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
或者,可以使用Array.reduceRight()和Set来跟踪已经访问过的姓名(如 @Felix Kling 所示) )
let input = [
{'name': 'a', 'val': 1},
{'name': 'b', 'val': 2},
{'name': 'a', 'val': 3},
{'name': 'b', 'val': 12},
{'name': 'c', 'val': 7},
{'name': 'b', 'val': 22}
];
let res = input.reduceRight((acc, obj) =>
{
if (acc.visited.has(obj.name))
return acc;
acc.visited.add(obj.name);
acc.res.unshift(obj);
return acc;
}, {res: [], visited: new Set()});
console.log(res.res);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}