Jack Jack - 2 months ago 6
Javascript Question

Mapping over an array of objects, then another array in those objects and getting rid of duplicates

I'm working on a function that gets an array of objects from an API, in those objects their is an array of tags, I want to return all the tags of those objects to populate a select field in my mark up. This is what I got so far and it's starting to get a bit confusing with all the maps I'm doing, its also returning the values but its returning them the same length of the original array of objects and get rid of any duplicates. What I'm I doing wrong or is their a better way to do this, and I'm using lodash?

renderOptions(){
let dataRef = this.props.designs.items,
tagArray = [],
newArr = []
return(_.map(dataRef, (design) => {
let tags = design.tags,
finalArr
return(_.map(tags, (tag) =>{
tagArray.push(tag)
newArr = [ ...new Set(tagArray) ]
return(_.map(newArr, (item) => {
console.log(item)
return( <li><h1>{item}</h1></li> )
}))
})
)
}))
}

Answer

Using reduce I have made the code more succinct, there's a working version on JS Bin. You'll have to adapt that to put in your framework (is it React?).

A good tip is to look out for the return types for lodash methods. The method reduce returns an array so this means we don't need to create a temporary array to hold our value and is assigned straight away to tags_array.

// assuming your data is something like this...
var objects = [
  {
    name: 'a',
    tags: ['a', 'b', 'c']
  },
  {
    name: 'b',
    tags: ['b', 'c', 'd']
  },
  {
    name: 'c',
    tags: ['a', 'c', 'd', 'e']
  }
]


var tags_array = _.uniq(                // returns a unique array.
  _.reduce(objects, function(i, o){     // iterates through objects and
    return o.tags;                      // returns o.tags each time
  })
);

console.log(tags_array);
// #=> ["a", "c", "d", "e"] 

So your function might work something like this, I'm guessing:

renderOptions(){
    let dataRef = this.props.designs.items;
    var tags_array = _.uniq(                // returns unique.
      _.reduce(dataRef, function(i, o){     // iterates through objects and
        return o.tags;                      // returns o.tags each time
      })
    );
    return tags_array;
 }

Then you could iterate through the array in your view, or adapt the renderOptions function to return the li html elements instead.

Comments