Find object by match property in nested array

I looked into this and I think the best option is to use Deepdash. It's a collection of methods to do deeply filter, find etc.

Sure it would be possible with lodash alone but with Deepdash it's easier.

I tried to convert the previous answer to the latest Lodash version but that was not working. Every method was deprecated in v4 of Lodash. Possible replacements: select = map or filter, any = some, where = filter)

findDeep returns an object with some information to the found item (just some values, see the docs for more details):

  • value is the object found
  • key that's the index in the nested array
  • parent the parent of the value

So the code for the findDeep looks like:

const modules = [{
  name: 'Module1',
  submodules: [{
    name: 'Submodule1',
    id: 1
  }, {
    name: 'Submodule2',
    id: 2
  }]
}, {
  name: 'Module2',
  submodules: [{
    name: 'Submodule1',
    id: 3
  }, {
    name: 'Submodule2',
    id: 4
  }]
}];

const getModule = (modules, id) =>
  _.findDeep(modules, module => module.id === id, {
    childrenPath: "submodules"
  });


const resultEl = document.getElementById("result");
const foundModule = getModule(modules, 3).value;

resultEl.innerText = JSON.stringify(foundModule, null, 2);
<script src="https://cdn.jsdelivr.net/npm/deepdash/browser/deepdash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
<script>
  deepdash(_);
</script>

<h2>Example to get module with id = 3</h2>
<pre id="result"></pre>

Here's what I came up with:

_.find(modules, _.flow(
    _.property('submodules'),
    _.partialRight(_.some, { id: 2 })
));
// → { name: 'Module1', ... }

Using flow(), you can construct a callback function that does what you need. When call, the data flows through each function. The first thing you want is the submodules property, and you can get that using the property() function.

The the submodules array is then fed into some(), which returns true if it contains the submodule you're after, in this case, ID 2.

Replace find() with filter() if you're looking for multiple modules, and not just the first one found.


I think your best chance is using a function, for obtaining the module.

_.select(modules, function (module) {
  return _.any(module.submodules, function (submodule) {
    return _.where(submodule, {id:3});
  });
});

try this for getting the submodule

.where(.pluck(modules, "submodules"), {submodules:{id:3}});


Lodash allows you to filter in nested data (including arrays) like this:

_.filter(modules, { submodules: [ { id: 2 } ]});

Tags:

Lodash