lodash property search in array and in nested chil

2019-01-24 02:22发布

I have this array:

[
    {
        id: 1,
        name: 'test 1',
        children: []
    },
    {
        id: 2,
        name: 'test 2',
        children: [
            {
                id: 4,
                name: 'test 4'
            }
        ]
    },
    {
        id: 3,
        name: 'test 3',
        children: []
    }
]

How can I filter by the id property in both this array and the nested children arrays?

For example, searching for id = 3, should return the test 3 object, and searching for id = 4 should return the test 4 object.

3条回答
贼婆χ
2楼-- · 2019-01-24 02:42

Another lodash option with children key and unlimited levels deep.

const flattenItems = (items, key) => {
    return items.reduce((flattenedItems, item) => {
        flattenedItems.push(item)
        if (Array.isArray(item[key])) {
            flattenedItems = flattenedItems.concat(flattenItems(item[key], key))
        }
        return flattenedItems
    }, [])
}

const item = find(flattenItems(items, 'children'), ['id', 4])
查看更多
我想做一个坏孩纸
3楼-- · 2019-01-24 02:44

That's a very simple tree traversal task. The easiest way to solve it is recursion (link to jsbin). It will work with any depth (with recursion limit of course) and it's one of the fastest ways with the worst complexity O(n):

function find(id, items) {
  var i = 0, found;

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      return items[i];
    } else if (_.isArray(items[i].children)) {
      found = find(id, items[i].children);
      if (found) {
        return found;
      }
    }
  }
}

Update:

To find all matches - a slightly modified function (jsbin link above is updated):

function findAll(id, items) {
  var i = 0, found, result = [];

  for (; i < items.length; i++) {
    if (items[i].id === id) {
      result.push(items[i]);
    } else if (_.isArray(items[i].children)) {
      found = findAll(id, items[i].children);
      if (found.length) {
        result = result.concat(found);
      }
    }
  }

  return result;
}
查看更多
戒情不戒烟
4楼-- · 2019-01-24 03:04

Using lodash, you can do something like this:

_(data)
    .thru(function(coll) {
        return _.union(coll, _.pluck(coll, 'children'));
    })
    .flatten()
    .find({ id: 4 });

Here, thru() is used to initialize the wrapped value. It's returning the union of the original array, and the nested children. This array structure is then flattened using flatten(), so you can find() the item.

查看更多
登录 后发表回答