1

I've recently been using lodash and I just love it. So I'm on a quest to learn it better.

For the past two days I've been trying to figure out how to do the following, without much success: considering an array of objects each with an array of objects in a property props...

let items = [{
  name: 'first',
  props: [{
    id: 1,
    name: 'one'
  }, {
    id: 2,
    name: 'two'
  }]
}, {
  name: 'second',
  props: [{
    id: 2,
    name: 'two'
  }]
}, {
  name: 'third',
  props: [{
    id: 1,
    name: 'one'
  }]
}];

... I'd like to create an array of objects containing each property in props across all items, each having an items property with all items containing that property, like this:

[{
  id: 1,
  name: 'one',
  items : [] // array containing objects `first` and 'third'
},{
  id: 2,
  name: 'two',
  items: [] // array containing objects `first` and 'second'
}]

I've tried various combinations inspired from answers of this question, which seems the closest I could find to what I'm trying to do.I think my real blocker is that, when trying to create an array of unique props (to which I'm going to map the items) and trying to use...

_(items).chain().flatten().pluck('props').unique().value()

... as in this answer, it tells me .chain(...).flatten(...).pluck is not a function. I also tried with .map instead of .pluck, but I guess not everything working in Underscore works in Lodash (I don't know the specific differences, I just read Lodash was forked from Underscore initially).

Note I know how to do this with classic fors and this is only an exercise. I don't have a practical use for it.

I'm just trying to learn to use lodash to its full potential. If you know how to do it, you don't even have to explain. I'll console.log() each step of the way until I understand what's going on. Also, if you think my question's name could be improved, for better indexing, considering what I want to achieve, I'm open to suggestions.

Ideally, the answer should be a chain of lodash methods, without declaring intermediary variables. I'm pretty sure it's doable (that's why I'm asking). Of course, the fewer steps the better — I assume it would impact performance in a real life scenario, but this is not a concern here — I'm aware that most times, when going for performance, the classic for loop is hard to beat.

1 Answer 1

1

First, let's transform each item to an array of props with the item's name, flatten this array of arrays, then the rest should be easier.

 _(data)
  .chain()
  .flatMap(({ props, name }) => _.map(props, p => ({
    id: p.id,
    name: p.name,
    item: name
  })))
  .groupBy(p => p.id)
  .map(props => ({
    id: _.head(props).id,
    name: _.head(props).name,
    items: _.map(props, p => p.item)
  }))
  .value();
4
  • The items inside the groups are not the initial objects, just their names, but it's close enough. Looking into flatmap() right now. Thank you.
    – tao
    Commented May 20, 2017 at 23:45
  • I didn't read it carefully enough, thought just names are needed, take a look at this line items: _.map(props, p => p.item) actually, you have all you need in props :)
    – rstar
    Commented May 20, 2017 at 23:53
  • Really helpful. Didn't know about _.head() or _flatMap() till now. I've made a playground here. Again, thank you.
    – tao
    Commented May 21, 2017 at 0:02
  • Btw, you can go _.map(props,'item') instead of _.map(props, p => p.item) in lodash now :). Same for .groupBy('id').
    – tao
    Commented May 21, 2017 at 1:18

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.