如何在JavaScript对象数组中查找重复值,并仅输出唯一值?

Ric*_*man 8 javascript arrays javascript-objects ecmascript-6

我正在学习JS.假设我有以下对象数组:

var family = [
  {
    name: "Mike",
    age: 10
  },
  {
    name: "Matt"
    age: 13
  },
  {
    name: "Nancy",
    age: 15
  },
  {
    name: "Adam",
    age: 22
  },
  {
    name: "Jenny",
    age: 85
  },
  {
    name: "Nancy",
    age: 2
  },
  {
    name: "Carl",
    age: 40
  }
];
Run Code Online (Sandbox Code Playgroud)

请注意,南希出现了两次(仅更改年龄).假设我只想输出唯一的名称.如何输出上面的对象数组,没有重复?ES6的答案非常受欢迎.

相关(找不到在对象上使用的好方法):

编辑这是我尝试过的.它适用于字符串,但我无法弄清楚如何使它与对象一起工作:

family.reduce((a, b) => {
  if (a.indexOf(b) < 0 ) {
    a.push(b);
  }
  return a;
},[]);
Run Code Online (Sandbox Code Playgroud)

Nin*_*olz 25

您可以在一行Set中结合使用Array#map扩展运算符 ....

Map返回一个包含所有名称的数组,这些名称将进入set初始值设定项,然后该数组的所有值都将返回到数组中.

var family = [{ name: "Mike", age: 10 }, { name: "Matt", age: 13 }, { name: "Nancy", age: 15 }, { name: "Adam", age: 22 }, { name: "Jenny", age: 85 }, { name: "Nancy", age: 2 }, { name: "Carl", age: 40 }],
    unique = [...new Set(family.map(a => a.name))];

console.log(unique);
Run Code Online (Sandbox Code Playgroud)

过滤和只返回唯一的名称,就可以使用Array#filterSet.

var family = [{ name: "Mike", age: 10 }, { name: "Matt", age: 13 }, { name: "Nancy", age: 15 }, { name: "Adam", age: 22 }, { name: "Jenny", age: 85 }, { name: "Nancy", age: 2 }, { name: "Carl", age: 40 }],
    unique = family.filter((set => f => !set.has(f.name) && set.add(f.name))(new Set));

console.log(unique);
Run Code Online (Sandbox Code Playgroud)

  • 有没有办法输出我的对象数组而不是这个平面数组? (2认同)

m0m*_*eni 11

解决方案

name在对象中存储循环外部的出现,并在先前出现的情况下进行过滤.

https://jsfiddle.net/nputptbb/2/

var occurrences = {}

var filteredFamily = family.filter(function(x) {
  if (occurrences[x.name]) {
    return false;
  }
  occurrences[x.name] = true;
  return true;
})
Run Code Online (Sandbox Code Playgroud)

您也可以将此解决方案概括为一个函数

function filterByProperty(array, propertyName) {
  var occurrences = {}

  return array.filter(function(x) {
    var property = x[propertyName]
    if (occurrences[property]) {
      return false;
    }
    occurrences[property]] = true;
    return true;
  })
}
Run Code Online (Sandbox Code Playgroud)

并使用它

var filteredFamily = filterByProperty(family, 'name')
Run Code Online (Sandbox Code Playgroud)

说明

不要比较使用的对象indexOf,它只===在对象之间使用运算符.你当前的答案不起作用的原因是因为===在JS中没有深入比较对象,而是比较了引用.我的意思是你可以在下面的代码中看到:

var a = { x: 1 }
var b = { x: 1 }

console.log(a === b) // false
console.log(a === a) // true
Run Code Online (Sandbox Code Playgroud)

Equality将告诉您是否找到了相同的对象,但如果找到具有相同内容的对象则不会.

在这种情况下,您可以比较您的对象,name因为它应该是唯一键.所以obj.name === obj.name代替obj === obj.此外,您的代码影响其运行时而不是其功能的另一个问题是您使用indexOf内部的reduce.indexOfO(n),这使您的算法的复杂性O(n^2).因此,最好使用具有O(1)查找功能的对象.

  • 我非常感谢这个答案 - 它具有跨浏览器,高性能和易于阅读的特点. (2认同)

Div*_*wat 5

这样就可以了。

const result = [1, 2, 2, 3, 3, 3, 3].reduce((x, y) => x.includes(y) ? x : [...x, y], []);

console.log(result);
Run Code Online (Sandbox Code Playgroud)