0

I have an object that looks like this:

const posts = [
               { id: 0, user: { id: 5564, name: 'john'} },
               { id: 1, user: { id: 5564, name: 'john'} },
               { id: 2, user: { id: 5560, name: 'jane'} }
              ]

I need an array of the unique user hashes like this:

[
 { id: 5564, name: 'john'},
 { id: 5560, name: 'jane'}
]

I'm able to retrieve all the users attributes from the posts array by doing:

const postUsers = posts.map(post => post.user)

which returns:

[
 { id: 5564, name: 'john'},
 { id: 5564, name: 'john'},
 { id: 5560, name: 'jane'}
]

where user john is listed twice

I've been able to get my desired result by doing:

const unique = {};
const uniqueUsers = [];
for(var i in postUsers){
  if(typeof(unique[postUsers[i].id]) == "undefined"){
    uniqueUsers.push(postUsers[i]);
  }
  unique[postUsers[i].id] = 0;
};
uniqueUsers

but there must be a cleaner way. I've also been able to return the unique ids of all users by doing:

var ids = posts.map(post => post.user.id)

var uniqueIds = Array.from(new Set(ids)).sort(); which returns [5564, 5560]

not sure if that helps. this article helped me a little https://medium.com/tomincode/removing-array-duplicates-in-es6-551721c7e53f

Jordan Running
  • 102,619
  • 17
  • 182
  • 182
alisontague
  • 319
  • 1
  • 4
  • 14

4 Answers4

0

You could take a Map and get only the unique users.

const
    posts = [{ id: 0, user: { id: 5564, name: 'john'} }, { id: 1, user: { id: 5564, name: 'john'} }, { id: 2, user: { id: 5560, name: 'jane'} }],
    unique = Array.from(posts.reduce((m, { user }) => m.set(user.id, user), new Map).values());

console.log(unique);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
0

If you don't mind using lodash you can do something like

const users = _map.(posts, 'user') // To get the list of users
_.uniqBy(users, 'id') // to get the uniq ones
0

Put the objects directly in uniqueUsers, then use Object.values() at the end to convert the object to an array.

const posts = [
   { id: 0, user: { id: 5564, name: 'john'} },
   { id: 1, user: { id: 5564, name: 'john'} },
   { id: 2, user: { id: 5560, name: 'jane'} }
];
let uniqueUsers = {};
posts.forEach(({user}) => uniqueUsers[user.id] = user);
uniqueUsers = Object.values(uniqueUsers);
console.log(uniqueUsers);
Barmar
  • 741,623
  • 53
  • 500
  • 612
0

Use reduce to reduce the array by checking if the value is already in the array. If it is already in the array, return the current state of the array, otherwise add the item to the array.

const posts = [
  { id: 0, user: { id: 5564, name: 'john'} },
  { id: 1, user: { id: 5564, name: 'john'} },
  { id: 2, user: { id: 5560, name: 'jane'} }
]

const r = posts.map(i => i.user).reduce((acc, itm) => {
  return !acc.find(i => i.id == itm.id) && acc.concat(itm) || acc
}, [])

console.log(r)
Get Off My Lawn
  • 34,175
  • 38
  • 176
  • 338