Filtering a deep array
I went functional on this one (as usual).

First of all, i removed the dependency from the third party library. I haven't anything in particular against that, but if the problem can be resolved easily with the standard tools, why bloat your app?

Then, since the main function deals mostly with lists, I looked for a way that would let me transform the list, filtering and transforming freely: reduce is a natural fit.

Now i can check the immediate list against a predicate (the filtering method you pass in) and recursively do the same on the list of childrens. The result of this filtering determines the final output structure.

Here's an implementation:



var data = [
    {
    name: 'a1', children: [
        {
        name: 'b1', children: [
            { name: 'gap' }, { name: 'bar' }
        ]
      }
    ]
  },
  {
    name: 'a2', children: [
        {
        name: 'b2', children: [
            { name: 'foo' }, { name: 'gap' }
        ]
      }
    ]
  }
];

function filterData(data, predicate) {

 // if no data is sent in, return null, otherwise transform the data
 return !!!data ? null : data.reduce((list, entry) =&gt; {

  let clone = null;
  if (predicate(entry)) {
   // if the object matches the filter, clone it as it is
   clone = Object.assign({}, entry)
  } else if (entry.children != null) {
   // if the object has childrens, filter the list of children
   let children = filterData(entry.children, predicate)
   if (children.length &gt; 0) {
    // if any of the children matches, clone the parent object, overwrite
    // the children list with the filtered list
    clone = Object.assign({}, entry, {children: children})
   }
  }

  // if there's a cloned object, push it to the output list
  clone &amp;&amp; list.push(clone)
  return list
 }, [])

}

var result = filterData(data, function(item) {
    return item.name === 'foo';
});

console.log(JSON.stringify(result, null, 2));




edit: I added some comments to the code. Shouldn't be needed, but it clarifies the steps.