0

Lodash's documentation for map() contains an example like this:

var users = [{'user': 'barney'}, {'user': 'fred'}];
_.map(users, 'user'); // => ['barney', 'fred']

I have data similar to that, but nested. Theirs is an array of objects, but I have an array of objects, each of which contains an array of objects, too. Expanding on the Lodash example, my data is like this:

var users = [
  {'mapping': [{'user': 'barney'}, {'user': 'fred'}]},
  {'mapping': [{'user': 'sherlock'}, {'user': 'watson'}]},
];

I'd like to get back all four of those names. (An array of arrays is acceptable.)

I tried a number of ways to do this. You can see my attempts at: https://runkit.com/lsloan0000/lodash-map-nested

Eventually, I found this solution:

// I didn't think it would take this much code
_.map(users, function (value, key, collection) {
    return _.map(value.mapping, 'user');
});

I thought Lodash has so many features that I wouldn't need to use a callback function.

Is there a simpler way to accomplish this?

I know I can probably skip the key and collection arguments. Eventually, I plan to have this code return the objects whose mapping contains two specific names. (All objects with mappings for "fred" and "barney" together.) So I've left those arguments there, because I think I will need them for that purpose.

1 Answer 1

1

Use _.flatMap() to flatten the nested array into a single array, and then map it to user values:

var users = [
  {'mapping': [{'user': 'barney'}, {'user': 'fred'}]},
  {'mapping': [{'user': 'sherlock'}, {'user': 'watson'}]},
];

var result = _(users)
  .flatMap('mapping')
  .map('user')
  .value();
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

And without a lodash chain:

var users = [
  {'mapping': [{'user': 'barney'}, {'user': 'fred'}]},
  {'mapping': [{'user': 'sherlock'}, {'user': 'watson'}]},
];

var result = _.map(_.flatMap(users, 'mapping'), 'user');
  
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>

4
  • I'll check out flatMap(). I think this solution won't fit with my stated goal of returning the objects whose mapping contains specific values, though. Maybe instead of posting a question about this specific step of my process, I should post one about the complete process (getting mappings, find those that match criteria, and return the objects that contain them). Commented Oct 3, 2017 at 18:30
  • You can achieve that easily by replacing the .map('user') with a filter, and a predicate you want the object to match. The result will be an array of objects.
    – Ori Drori
    Commented Oct 3, 2017 at 18:34
  • OK. Can you explain why you used chaining in your solution. I'd read that chaining in Lodash isn't a great idea because the program is virtually forced to load the full version of Lodash. Supposedly, using chaining a Lodash subset works, but the loading of other modules with Lodash functions is problematic. Commented Oct 3, 2017 at 19:04
  • The problem with chaining is that you can't load lodash in a modular way (ie just the parts you need). I've used it in this case, because it's easier to understand then a method inside a method (see 2nd example).
    – Ori Drori
    Commented Oct 3, 2017 at 20:29

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.