使用ES6在数组中查找不同的对象

7
我有一个如下所示的数组。
const data = [
    {
        name:'AAAA',
        group: 'A',
        age:10
    },
    {
        name:'ABCD',
        group: 'A',
        age:10
    },
    {
        name:'DJSHDJH',
        group: 'B',
        age:15
    },
    {
        name:'FJHF',
        group: 'B',
        age:20
    }
]

我希望通过es6groupage查找不同的数据。

期望结果:

[
    {
        group: 'A',
        age: 10
    },
    {
        group: 'B',
        age: 15
    },
    {
        group: 'B',
        age: 20
    }
]

我尝试使用[... new Set(data.map(x => {x.group, g.age}))],但没有成功

我知道如何遍历数据并查找唯一值,但我想使用es6函数


你想要筛选和映射还是只是归约? - epascarello
@epascarello,filter里面有什么? - Reza
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/filter - epascarello
@epascarello 我知道什么是过滤器以及如何使用它,但是过滤器如何解决我的问题呢?我需要按组和年龄获取唯一值。 - Reza
因为您使用循环来过滤唯一的组和年龄... - epascarello
在我看来,使用“减少”更为恰当。@epascarello - Andrew Li
3个回答

10
您可以使用Object.values()reduce()一起,以返回值数组作为结果。

const data = [{"name":"AAAA","group":"A","age":10},{"name":"ABCD","group":"A","age":10},{"name":"DJSHDJH","group":"B","age":15},{"name":"FJHF","group":"B","age":20}]

var result = Object.values(data.reduce((r, e) => (r[e.group + '|' + e.age] = {group: e.group, age: e.age}, r), {}))
console.log(result)

模板字面量属性值简写是根据@Jeremy Thille的建议编写相同代码的另一种方式。

const data = [{"name":"AAAA","group":"A","age":10},{"name":"ABCD","group":"A","age":10},{"name":"DJSHDJH","group":"B","age":15},{"name":"FJHF","group":"B","age":20}]

var result = Object.values(data.reduce(function(r, e) {
  let group = e.group, age = e.age;
  return r[`${group}|${age}`] = {group, age}, r
}, {}))

console.log(result)

您还可以使用ES6参数解构,如@gyre所建议的。

const data = [{"name":"AAAA","group":"A","age":10},{"name":"ABCD","group":"A","age":10},{"name":"DJSHDJH","group":"B","age":15},{"name":"FJHF","group":"B","age":20}]

var result = Object.values(data.reduce((r, {group, age}) => (r[group+'|'+age] = {group, age}, r), {}))
console.log(result)


1
r[e.group + '|' + e.age] 已经过时了,使用 r[\${e.group}|${e.age}`]` 代替。不过还是点赞的。 - Jeremy Thille
1
有人能解释一下在= {group: e.group, age: e.age}, r中的, r是做什么的吗? - Alexander Staroselsky
1
逗号运算符将返回最后一项 (r, e) => { (r[e.group + '|' + e.age] = {group: e.group, age: e.age}; return r} - epascarello
你还可以使用“解构参数”{group,age}替换e来简化减少函数的代码。 - gyre
@gyre 谢谢,太棒了。 - Nenad Vracar

2

像Nenad的代码一样使用查找表是完成这项工作的正确方式,但为了增加变化,我包括了一种通过排序和简化来解决问题的方法,显然不太有效率。

var data   = [{"name":"AAAA","group":"A","age":10},
              {"name":"DJSHDJH","group":"B","age":15},
              {"name":"ABCD","group":"A","age":10},
              {"name":"FJHF","group":"B","age":20},
              {"name":"ABCD","group":"A","age":12},
              {"name":"SOLUS","group":"B","age":15},],
    result = data.sort((a,b) => a.group.localeCompare(b.group) || a.age - b.age)
                 .reduce((r,c,i) => i ? r[r.length-1].group == c.group && r[r.length-1].age == c.age ? r 
                                                                                                     : r.concat({group:c.group, age:c.age})
                                      : [{group:c.group, age:c.age}], []);
console.log(result);


1

另一种更易读但更冗长的方法是:

var filteredData = [];
data.forEach((item)=>{
    if(!filteredData.some(x=>x.group === item.group && x.age === item.age)){
        filteredData.push(item);
    }
});

// then you can change your result array if you want by using map
var result = filteredData.map(x=>{name:x.name,age:x.age});

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接