lodash 属性 在数组和嵌套的子数组中搜索

lodash property search in array and in nested child arrays

我有这个数组:

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

如何按此数组 嵌套 children 数组中的 id 属性 进行过滤?

例如,搜索 id = 3,应该 return test 3 对象,搜索 id = 4 应该 return test 4对象。

使用 lodash,你可以做这样的事情:

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

此处,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() 项目。

这很简单 tree traversal task. The easiest way to solve it is recursion (link to jsbin)。它适用于任何深度(当然有递归限制)并且它是最快的方法之一,复杂度最差 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;
      }
    }
  }
}

更新:

查找所有匹配 - 一个稍微修改的函数(上面的 jsbin link 已更新):

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;
}

另一个 lodash 带有子键和无限深度的选项。

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])

您可以使用带有 ES6 语法的纯 javascript 来实现此目的:

  • 首先你可以用.reduce函数
  • 展平数组
  • 然后你可以用.find搜索你要找的id

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

const flattenData = arr.reduce((newArr, arr) => {
  const {children, ...rest } = arr;
  newArr.push(rest);
  return newArr.concat(children)
}, [])


console.log(flattenData.find(d=>d.id===4))