Vincent Ducorps
Vincent Ducorps

Reputation: 55

How to create a new array of objects form object without duplicates ? (ES6)

I would like to create an array of all "department" from the "users" array without duplicate in ES6. I've tried with forEach, reduce, filter, without success...

Users array:

let users = [{
    firstname: 'test',
    department: {
      id: 1,
      name: 'hello'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 2,
      name: 'hello2'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 1,
      name: 'hello'
    }
  }
]

Result expected:

// Expected 
departments = [{
    id: 1,
    name: 'hello'
  },
  {
    id: 2,
    name: 'hello2'
  }
] */

My own experiment:

let departments = []
users.forEach(user => {
  console.log('-------------------')
  console.log(departments)
  console.log(user)
  console.log(user.department)
  console.log(departments.includes(user.department))

  if (!departments.includes(user.department)) {
    departments.push(user.department)
  }
  console.log(departments)
})

console.log(departments)

Thanks for your help!

Upvotes: 2

Views: 122

Answers (3)

cнŝdk
cнŝdk

Reputation: 32145

Problem:

Your problem is that you are checking for departments with Array#includes() which is rather used with primitives such as Number and string and doesn't compare objects, try not to use it as it's not compatible with IE also.

Solution:

You can do it using Array#map() and Array#filter() methods:

var deps = users.map(u => u.department);

let results = deps.filter((item, pos) => {
 return deps.map(v => v.id).indexOf(item.id) == pos;
});
  • First map the items to keep only the department object.
  • Then filter the departments to exclude the ones that has the same id.

Demo:

This is a working demo:

let users = [{
    firstname: 'test',
    department: {
      id: 1,
      name: 'hello'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 2,
      name: 'hello2'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 1,
      name: 'hello'
    }
  }
];

var deps = users.map(u => u.department);

let results = deps.filter((item, pos) => {
 return deps.map(v => v.id).indexOf(item.id) == pos;
});

console.log(results);

Upvotes: 4

Jonas Wilms
Jonas Wilms

Reputation: 138307

Just map to the departments, then filter out based on the id:

  const ids = new Set;

 const result = users
   .map(user => user.department)
   .filter(({ id }) => !ids.has(id) && ids.add(id));

(This is O(n) as Set lookup / insertion is O(1))

Upvotes: 3

Ankit Agarwal
Ankit Agarwal

Reputation: 30739

You can use Array.reduce() for that:

let users = [{
    firstname: 'test',
    department: {
      id: 1,
      name: 'hello'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 2,
      name: 'hello2'
    }
  },
  {
    firstname: 'test2',
    department: {
      id: 1,
      name: 'hello'
    }
  }
];

let departments = users.reduce((acc, obj)=>{
  let exist = acc.find(({id}) => id === obj.department.id);
  if(!exist){
    acc.push({id:obj.department.id, name: obj.department.name});
  }
  return acc;
}, []);
console.log(departments);

Upvotes: 2

Related Questions