繁体   English   中英

如何从 JavaScript 数组中删除重复的 OBJECTS?

[英]How to remove duplicated OBJECTS from JavaScript array?

从对象数组中删除重复对象的最佳方法是什么?

var arr = 
    [
        {"name":"Joe", "age":17}, 
        {"name":"Bob", "age":17}, 
        {"name":"Carl", "age": 35},
        {"name":"Bob", "age":35},
        {"name":"Joe", "age":17}, 
    ]

删除重复项时,预期结果是

res= arr = 
    [
        {"name":"Joe", "age":17}, 
        {"name":"Bob", "age":17}, 
        {"name":"Carl", "age": 35},
        {"name":"Bob", "age":35},
    ]

(5 个对象,1 个重复,剩下 4 个)。

每个对象的属性数量是固定的,每个数组的属性名称都相同。 然而,从数组到数组,它们可能不仅仅是上面的“名称”和“年龄”,而是属性的名称可以是任何。

@Pointy 请将上述问题中的重复词视为口头意义上的“重复” - 对象分别具有相同数量的属性、相同的属性和相同的属性值。

这不是从 JavaScript 数组中删除重复项的重复项

无论是否插入对象,都可以使用对象进行查找。

编辑:

更新以获取对象的所有属性,并使用键的值。 如果仅应使用某些属性,则建议使用带有相关键的数组,例如

['name', 'age']

并与

var key = ['name', 'age'].map(function (k) { return a[k]; }).join('|');

 var arr = [{ "name": "Joe", "age": 17 }, { "name": "Bob", "age": 17 }, { "name": "Carl", "age": 35 }, { "name": "Bob", "age": 35 }, { "name": "Joe", "age": 17 }], filtered = arr.filter(function (a) { var key = Object.keys(a).map(function (k) { return a[k]; }).join('|'); if (!this[key]) { return this[key] = true; } }, Object.create(null)); console.log(filtered); 

使用Object.keysArray.everyArray.concat函数的解决方案:

var names = {}, result = [];
arr.forEach(function (v) {
    var name = v['name'];
    names[name] = names[name] || [];
    // considering multiple objects with same 'name' but different 'age' - and vise versa
    if (!Object.keys(names[name]).length ||  
        names[name].every((obj) => ((obj['name'] === name && obj['age'] !== v['age']) || (obj['name'] !== name && obj['age'] === v['age'])) )) {
        names[name].push(v);
    }
}, names);
Object.keys(names).forEach((k) => result = result.concat(names[k]), result);

console.log(JSON.stringify(result, 0, 4));

输出:

[
    {
        "name": "Joe",
        "age": 17
    },
    {
        "name": "Bob",
        "age": 17
    },
    {
        "name": "Bob",
        "age": 35
    },
    {
        "name": "Carl",
        "age": 35
    }
]

这是从对象数组中过滤任何平面对象(非嵌套对象)的重复项的通用解决方案。 不针对此特定问题。 否则,可以根据已知的属性和值通过建立LUT(例如,由Map对象组成的查找表)来轻松完成此工作。 同样,您可以将此解决方案应用于任何对象数组以删除重复对象。

Object.prototype.compare()的发明是执行此任务的最佳方法,因此一旦掌握了该任务,该工作将只不过是一个游戏。 让我们来看看它。

 Object.prototype.compare = function(o){ var ok = Object.keys(this); return typeof o === "object" && ok.length === Object.keys(o).length ? ok.every(k => this[k] === o[k]) : false; }; var arr = [ {"name":"Joe", "age":17}, {"name":"Bob", "age":17}, {"name":"Carl", "age": 35}, {"name":"Bob", "age":35}, {"name":"Joe", "age":17}, ], red = arr.reduce((p,c,i) => {var f = p.slice(i).findIndex(o => o.compare(p[i-1])); return f == -1 ? p : (p.splice(f+i,1),p)},arr); console.log(JSON.stringify(arr,null,2)); 

我相信到目前为止,这是最好的方法。 我当然更喜欢Map或Set,但是从ES6的这个版本开始,即使我们可以将对象用作Map对象中的键,它们仍然不能用于访问值。 我的意思是,即使键对象是一个空对象,另一个空对象也不会定义该键。 但是我认为这是一项工作,因为在Map对象中, NaN可以是一个密钥,即使在JS世界中,您都可以使用NaN来访问它,因为您都知道NaN !== NaN

var m = new Map();
m.set({},true);
m.set("a",1);
m.set(NaN,"cow");
m.get({},true};   // undefined
m.get("a",1);     // 1
m.get(NaN,"cow"); // "cow" so NaN == NaN is true in the Map ...
const arr1 = [{"name":"ren","age":3,"weight":120},{"name":"ren","age":2,"weight":100},{"name":"ren","age":2,"weight":100},{"name":"ren","age":2,"weight":100},{"name":"ren","age":2,"weight":100},{"name":"ren","age":2,"weight":100},{"name":"ren","age":1,"weight":100},{"name":"stimpy","age":2,"weight":100},{"name":"george american","age":56,"weight":220}]
const arr2 = [{"name":"ren","age":2,"weight":150},{"name":"ren","age":2,"weight":150},{"name":"ren","age":2,"weight":150},{"name":"ren","age":2,"weight":100},{"name":"stimpy","age":2,"weight":100},{"name":"ren","age":3,"weight":100},{"name":"stimpy","age":1,"weight":100},{"name":"ren","age":2,"weight":100},{"name":"circus midgets","age":5,"weight":200}]

function uniq_all_props (__arr1, __arr2) {
  let arr = __arr1.concat(__arr2)
  console.log('arr.length', arr.length)
  let set = []
  let result = []
  arr.forEach(function (__obj) {
    /** Set each obj to a string. */
    let string = JSON.stringify(__obj)
    set.push(string)
  })
  set.filter(function (elem, index, self) {
    /** Use filter as a loop to push onto results array.
     * This is done to preserve prop types from original arrays */
    if (index === self.indexOf(elem)) {
      result.push(arr[index])
    }
  })
  return result
}


console.log(uniq_all_props(arr1, arr2))

根据 ID 将 Array 转换为 JSON,然后将其转换为 Array。

    const json = {};
    this.data.forEach(ele => {
      json[ele['id']] = ele;
    });
    console.log(Object.values(json));

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM