7

I have an array like below

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
    }
]

I want to find distinct data by group and age by es6

expected result

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

I tried using [... new Set(data.map(x => {x.group, g.age}))] but no chance

I know how to loop through data and find unique values, but I want to use es6 functions

6
  • You want filter and map or just reduce Commented Aug 3, 2017 at 14:03
  • @epascarello, what is in filter? Commented Aug 3, 2017 at 14:04
  • developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… Commented Aug 3, 2017 at 14:04
  • @epascarello I know what is filter and how to use it, how does filter solve my problem? I need unique values by group and age Commented Aug 3, 2017 at 14:06
  • because you use to to loop over and filter out the unique groups and ages.... Commented Aug 3, 2017 at 14:06

3 Answers 3

10

You can use Object.values() with reduce() to return array of values as result.

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)

Another way of writing the same code as suggested by @Jeremy Thille is using template literals and property value shorthand

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)

You can also use ES6 parameter destructuring as suggested by @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)

Sign up to request clarification or add additional context in comments.

5 Comments

r[e.group + '|' + e.age] is so ES5. Use r[`${e.group}|${e.age}`] but upvoted nonetheless
Can someone explain what the portion , r in = {group: e.group, age: e.age}, r is doing?
Comma operator will return the last item (r, e) => { (r[e.group + '|' + e.age] = {group: e.group, age: e.age}; return r}
You can also use the destructuring parameter { group, age } in place of e to simplify the body of the reduction function
@gyre Thanks men, that's great.
2

Utilizing a lookup table just like Nenad's code is the right way to do this job however just for a variety i include a solution by sorting and reducing which is obviously less efficient.

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);

Comments

1

Another way of doing this, more readable but longer way is:

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});

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.