Javascript 删除对象数组Javascript中的重复项
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/36032179/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Remove duplicates in an object array Javascript
提问by kwn
I have an array of objects
我有一个对象数组
list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}]
And I'm looking for an efficient way (if possible O(log(n))
) to remove duplicates and to end up with
我正在寻找一种有效的方法(如果可能的话O(log(n))
)来删除重复项并最终得到
list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}]
I've tried _.uniq
or even _.contains
but couldn't find a satisfying solution.
我已经尝试过_.uniq
甚至_.contains
但找不到令人满意的解决方案。
Thanks!
谢谢!
Edit : The question has been identified as a duplicate of another one. I saw this question before posting but it didn't answer my question since it's an array of object (and not a 2-dim array, thanks Aaron), or at least the solutions on the other question weren't working in my case.
编辑:该问题已被确定为另一个问题的重复。我在发布之前看到了这个问题,但它没有回答我的问题,因为它是一个对象数组(而不是一个二维数组,谢谢 Aaron),或者至少另一个问题的解决方案在我的情况下不起作用。
采纳答案by Andy
Vanilla JS version:
香草JS版本:
const list = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];
function dedupe(arr) {
return arr.reduce(function(p, c) {
// create an identifying id from the object values
var id = [c.x, c.y].join('|');
// if the id is not found in the temp array
// add the object to the output array
// and add the key to the temp array
if (p.temp.indexOf(id) === -1) {
p.out.push(c);
p.temp.push(id);
}
return p;
// return the deduped array
}, {
temp: [],
out: []
}).out;
}
console.log(dedupe(list));
回答by isvforall
回答by Lava kumar N R
Try using the following:
尝试使用以下方法:
list = list.filter((elem, index, self) => self.findIndex(
(t) => {return (t.x === elem.x && t.y === elem.y)}) === index)
回答by dhilt
I would use a combination of Arrayr.prototype.reduce
and Arrayr.prototype.some
methods with spread operator.
我会使用Arrayr.prototype.reduce
和Arrayr.prototype.some
方法与扩展运算符的组合。
1. Explicit solution. Based on complete knowledge of the array object contains.
1. 明确的解决方案。基于数组对象包含的完整知识。
list = list.reduce((r, i) =>
!r.some(j => i.x === j.x && i.y === j.y) ? [...r, i] : r
, [])
Here we have strict limitation on compared objects structure: {x: N, y: M}
. And [{x:1, y:2}, {x:1, y:2, z:3}]
will be filtered to [{x:1, y:2}]
.
这里我们对比较对象的结构有严格的限制:{x: N, y: M}
. 而[{x:1, y:2}, {x:1, y:2, z:3}]
将被过滤[{x:1, y:2}]
。
2. Generic solution, JSON.stringify()
. The compared objects could have any number of any properties.
2. 通用解决方案,JSON.stringify()
。比较对象可以具有任意数量的任何属性。
list = list.reduce((r, i) =>
!r.some(j => JSON.stringify(i) === JSON.stringify(j)) ? [...r, i] : r
, [])
This approach has a limitation on properties order, so [{x:1, y:2}, {y:2, x:1}]
won't be filtered.
这种方法对属性顺序有限制,因此[{x:1, y:2}, {y:2, x:1}]
不会被过滤。
3. Generic solution, Object.keys()
. The order doesn't matter.
3. 通用解决方案,Object.keys()
。顺序无关紧要。
list = list.reduce((r, i) =>
!r.some(j => !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])
This approach has another limitation: compared objects must have the same list of keys.
So [{x:1, y:2}, {x:1}]
would be filtered despite the obvious difference.
这种方法还有另一个限制:比较对象必须具有相同的键列表。所以[{x:1, y:2}, {x:1}]
会尽管有明显的差异进行过滤。
4. Generic solution, Object.keys()
+ .length
.
4. 通用解决方案,Object.keys()
+ .length
。
list = list.reduce((r, i) =>
!r.some(j => Object.keys(i).length === Object.keys(j).length
&& !Object.keys(i).some(k => i[k] !== j[k])) ? [...r, i] : r
, [])
With the last approach objects are being compared by the number of keys, by keys itself and by key values.
对于最后一种方法,对象通过键的数量、键本身和键值进行比较。
I created a Plunkerto play with it.
我创建了一个Plunker来玩它。
回答by Nina Scholz
Filter the array after checking if already in a temorary object in O(n).
在检查是否已经在 O(n) 中的临时对象中后过滤数组。
var list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }],
filtered = function (array) {
var o = {};
return array.filter(function (a) {
var k = a.x + '|' + a.y;
if (!o[k]) {
o[k] = true;
return true;
}
});
}(list);
document.write('<pre>' + JSON.stringify(filtered, 0, 4) + '</pre>');
回答by baao
The following will work:
以下将起作用:
var a = [{x:1,y:2}, {x:3,y:4}, {x:5,y:6}, {x:1,y:2}];
var b = _.uniq(a, function(v) {
return v.x && v.y;
})
console.log(b); // [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 } ]
回答by chickens
One liners for ES6+
一个 ES6+ 的衬垫
If you want to find uniq by x and y:
如果你想通过 x 和 y 找到 uniq:
arr.filter((v,i,a)=>a.findIndex(t=>(t.x === v.x && t.y===v.y))===i)
If you want to find uniques by all properties:
如果要按所有属性查找唯一值:
arr.filter((v,i,a)=>a.findIndex(t=>(JSON.stringify(t) === JSON.stringify(v)))===i)
回答by Simon
Using lodash you can use this one-liner:
使用 lodash 你可以使用这个单行:
_.uniqBy(list, e => { return e.x && e.y })