2

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!

3
  • 1
    Post the code you say you've tried Commented Aug 23, 2018 at 13:59
  • Using _.uniqBy from lodash might be a good solution ;) Commented Aug 23, 2018 at 14:02
  • @Finrod Thanks but I prefer vanilla in this case ;) Commented Aug 23, 2018 at 14:10

3 Answers 3

4

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

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

Comments

3

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

Comments

2

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

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.