1

I have a given array of objects something like:

var items = [
{item: [{foo: 21, bar: 'a' }, {foo: 5,bar: 'e'},{foo: 167, bar: 'c'}]},
{item: [{foo: 42, bar: 'a' }, {foo: 45,bar: 'd'},{foo: 7, bar: 'c'}]},
{item: [{foo: 99, bar: 'b' }, {foo: 35,bar: 'c'},{foo: 22, bar: 'e'}]},
{item: [{foo: 31, bar: 'e' }, {foo: 22,bar: 'd'},{foo: 12, bar: 'a'}]}
]

and I would like to get a new array that returns the unique values of all the bar values, so it would look something like:

var uniqueBars = ['a','b','c','d','e'];

I have a solution for this by looping through all of the items, but I'm guessing there is a more efficient way to do this using ES6 features.

Is there a way to create the uniqueBars array above using ES6 features?

4 Answers 4

2

Iterate over items with flatMap and for each inner array map over those objects to return each bar value. Shove the resulting sorted flat array into a Set to remove the duplicates and then spread that back out into an array so you can log the deduped values.

const items=[{item:[{foo:21,bar:"a"},{foo:5,bar:"e"},{foo:167,bar:"c"}]},{item:[{foo:42,bar:"a"},{foo:45,bar:"d"},{foo:7,bar:"c"}]},{item:[{foo:99,bar:"b"},{foo:35,bar:"c"},{foo:22,bar:"e"}]},{item:[{foo:31,bar:"e"},{foo:22,bar:"d"},{foo:12,bar:"a"}]}];

// For each `obj.item.map` you'll get a nested array of
// bar values from each object. Use `flatMap` on that array
// to get all the values into one array, and then sort it
const flattened = items.flatMap(obj => {
  return obj.item.map(inner => inner.bar);
}).sort();

// Pass the flattened array into a new Set
// and use spread to work that set into a new array
const deduped = [...new Set(flattened)];

console.log(deduped);

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

Comments

1

You could supply a path of keys and get the values for a Set.

const
    getValues = (data, [key, ...keys]) => data.flatMap(o => keys.length
        ? getValues(o[key], keys)
        : o[key]
    ),
    items = [{ item: [{ foo: 21, bar: 'a' }, { foo: 5, bar: 'e' }, { foo: 167, bar: 'c' }] }, { item: [{ foo: 42, bar: 'a' }, { foo: 45, bar: 'd' }, { foo: 7, bar: 'c' }] }, { item: [{ foo: 99, bar: 'b' }, { foo: 35, bar: 'c' }, { foo: 22, bar: 'e' }] }, { item: [{ foo: 31, bar: 'e' }, { foo: 22, bar: 'd' }, { foo: 12, bar: 'a' }] }],
    keys = ['item', 'bar'],
    unique = [...new Set(getValues(items, keys))];

console.log(...unique);

Comments

1

Here a one-liner (not sure it's the best way though) :

[...new Set(items.map(obj => obj.item.map(o => o.bar)).flat())]

As suggested by @Mulan and @Andy, instead of [].map().flat(), prefer flatMap():

[...new Set(items.flatMap(obj => obj.item.map(o => o.bar)))]

2 Comments

.map(...).flat() is the reason .flatMap(...) exists. you will reduce iterations by half
not sure it's the best way though I was editing my post referring to flatMap(), but your comment and @Andy 's answer came first :)
0

you could loop through the array of objects and then have a lookups, on the new array

like this

let uniqueBars = []; 
items.foreach = (item) => {
   const itemInNewArray = uniqueBars.find(bar => bar == item.bar);
   if (!itemInNewArray) {
      uniqueBars.push(item.bar)
   }
}

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.