从数组中删除重复项

IT技术 javascript arrays
2021-01-20 23:26:42

我有一个看起来像这样的对象数组:

var array = [
    {id:123, value:"value1", name:"Name1"},
    {id:124, value:"value2", name:"Name1"},
    {id:125, value:"value3", name:"Name2"},
    {id:126, value:"value4", name:"Name2"}
    ...
];

如您所见,有些名称是重复的。我想获得一个只有名称的新数组,但如果某些名称重复,我不想再次添加它。我想要这个数组:

var newArray = ["Name1", "Name2"];

我正在尝试这样做map

var newArray = array.map((a) => {
    return a.name;
});

但问题是这会返回:

newArray = ["Name1", "Name1", "Name2", "Name2"];

我怎样才能在里面设置一些条件map,这样它就不会返回一个已经存在的元素?我想用map或其他一些 ECMAScript 5 或 ECMAScript 6 功能来做到这一点

6个回答

使用 ES6,您可以Set在仅映射对象名称之后使用唯一值。

该提案使用扩展语法...来收集新数组中的项目。

const array = [{ id: 123, value: "value1", name:"Name1" }, { id: 124, value: "value2", name: "Name1" }, { id: 125, value: "value3", name: "Name2" }, { id: 126, value: "value4", name: "Name2" }],
      names = [...new Set(array.map(a => a.name))];

console.log(names);

对于我的信息..有什么作用...
2021-03-15 23:26:42
我不赞成“Set”本身,而是赞成对扩展运算符的巧妙使用。学习新东西或看到新东西应用于实际示例总是很好,所以这篇文章值得点赞。
2021-03-15 23:26:42
@RajshekarReddy,这是一种用于构建具有可迭代对象的数组扩展语法...
2021-03-22 23:26:42
@KRyan ES6 这么新吗?它已于 2015 年 6 月完成。是时候开始了解和使用新功能了
2021-03-26 23:26:42
这只是我个人的意见,但相当普遍使用可以Array.from更好地传达转换的意图(并且也更容易理解/搜索新手),应仅在扩展元素是众多元素之一时使用扩展语法。也许称其为“不良做法”有点太苛刻了,对不起,我只是希望防止它成为一种常见的习语。
2021-03-31 23:26:42

如果您正在寻找非 ES 6(无设置)的 JavaScript 解决方案,您可以使用Array 的reduce方法

var array=[
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];
var names = array.reduce(function (a, b) {
  if (a.indexOf(b.name) == -1) {
    a.push(b.name)
  }
  return a;
}, []);

console.log(names);

这个答案还有一个好处,它不需要中间数组或集合,尤其是那些只包含名称本身的数组或集合。(它直接从对象数组转到对象数组。)+1
2021-03-23 23:26:42
@Rayon 请不要过分关注源代码的大小,这是许多自制程序员的常见陷阱,最重要的是,您的程序应该高效且可读。
2021-03-26 23:26:42
是的,但它不像排序或过滤器那样直接从一个到另一个,它是从一个空数组重建的。
2021-03-27 23:26:42
@Dekel — 较小的版本 :) var names = array.reduce(function(a, b) { a.indexOf(b.name) === -1 && a.push(b.name) return a; }, []);
2021-04-05 23:26:42
@Iwrestledabearonce,这第二个参数与返回的参数不是同一个对象吗?
2021-04-06 23:26:42

我个人不明白为什么每个人都喜欢 ES 6。如果是我的代码,我更愿意支持尽可能多的浏览器。

var array=[
{id:123, value:"value1", name:"Name1"},
{id:124, value:"value2", name:"Name1"},
{id:125, value:"value3", name:"Name2"},
{id:126, value:"value4", name:"Name2"}
];

   // Create array of unique names
var a = (function(a){
  for (var i = array.length; i--;)
    if (a.indexOf(array[i].name) < 0) a.push(array[i].name);
  return a;
})([]);

console.log(a);

“我指的是著名的 Apple SSL 错误”——并不是那么出名,你可以脱离上下文在随机评论中引用它并期望人们能够识别它。
2021-03-19 23:26:42
更具可读性?它是一个可怕的 for 循环,它将项目推送到数组上。没有比这更具可读性的了......
2021-03-22 23:26:42
老实说,这感觉就像你太努力了,找不到可以抱怨的东西。
2021-03-28 23:26:42
将对象用作字典而不是一直使用indexOf-ing会不会更高效?例如做added[name] = trueif(added[name])而不是if(a.indexOf(name))
2021-04-04 23:26:42
“就我个人而言,我不明白为什么每个人都对 es6 情有独钟”为什么你要追求一个goto fail,将你的索引变量泄漏到封闭的范围内等等。ES6 被编入标准有充分的理由,并且是最重要的对于较旧的浏览器,这部分很容易填充/转换。
2021-04-10 23:26:42

你也可以简单地结合起来mapfilter

var array = [
  {id:123, value:"value1", name:"Name1"},
  {id:124, value:"value2", name:"Name1"},
  {id:125, value:"value3", name:"Name2"},
  {id:126, value:"value4", name:"Name2"}
];

var unique = array
  .map( item => item.name )
  .filter( ( item, idx, arr ) => arr.indexOf( item ) == idx ) 

console.log(unique)

您可以使用Object.keys()array使用Array.prototype.reduce()迭代变量的对象结果中获取给定对象自己的可枚举属性名称的数组,其中键是被破坏的名称

代码:

const array = [{id:123, value:"value1", name:"Name1"}, {id:124, value:"value2", name:"Name1"}, {id:125, value:"value3", name:"Name2"}, {id:126, value:"value4", name:"Name2"}],
      names = Object.keys(
        array.reduce((a, { name }) => (a[name] = 1, a), {})
      )

console.log(names)