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

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-23 18:32:14  来源:igfitidea点击:

Remove duplicates in an object array Javascript

javascriptarraysunderscore.js

提问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 _.uniqor even _.containsbut 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

Plain javascript (ES2015), using Set

纯 javascript (ES2015),使用 Set

const list = [{ x: 1, y: 2 }, { x: 3, y: 4 }, { x: 5, y: 6 }, { x: 1, y: 2 }];

const uniq = new Set(list.map(e => JSON.stringify(e)));

const res = Array.from(uniq).map(e => JSON.parse(e));

document.write(JSON.stringify(res));

回答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.reduceand Arrayr.prototype.somemethods with spread operator.

我会使用Arrayr.prototype.reduceArrayr.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 })