1

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> )
                    }))
                })
            )
        }))
     }
4
  • are you using lodash or underscore?
    – user115014
    Commented Sep 8, 2016 at 15:02
  • Sorry did I miss that about lodash? I don't understand about duplicates: you do or you don't want duplicates? I'm guessing you don't but just to confirm...
    – user115014
    Commented Sep 8, 2016 at 15:20
  • Yeah, I'm trying to get rid of duplicates, using the ES6 new Set syntax
    – Jack
    Commented Sep 8, 2016 at 15:25
  • You're re-instantiating newArr on every iteration during the second map. Are you perhaps intending to use concat? ie: newArr = newArr.concat(...new Set(tagArray));
    – DRAB
    Commented Sep 8, 2016 at 15:26

2 Answers 2

1

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.

The reduce method can be used too as Palermo mentioned below:

let tags_array = objects.reduce((i, o) => { return o.tags; });

so lodash is not needed.

1
  • I completely forgot about reduce, this is a very nice solution. Thanks!
    – Jack
    Commented Sep 8, 2016 at 16:07
0

You don't even need lodash to do this. Here is an even cleaner way to do this

let tags_array = dataRef.reduce((i, o) => { return o.tags; });
1
  • Brilliant, I'll add to answer
    – user115014
    Commented Sep 9, 2016 at 8:45

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.