如何使用Lodash / JS递归过滤嵌套对象?

时间:2018-09-06 13:39:44

标签: javascript recursion multidimensional-array filter lodash

我有一个数组,其中包含深度未知的对象,像这样

var objects = [{
    id: 1,
    name: 'foo'
}, {
    id: 2,
    name: 'bar',
    childs: [{
        id: 3,
        name: 'baz',
        childs: [{
            id: 4,
            name: 'foobar'
        }]
    }]
}];

我希望能够通过其ID过滤特定的子对象。

当前,我正在使用这个小lodash脚本(从this question引用),但是它仅适用于不深于一层的对象。因此,搜索id: 1id: 2会很好,而搜索id: 3id: 4会返回undefined。

function deepFilter(obj, search) {
    return _(obj)
        .thru(function(coll) {
            return _.union(coll, _.map(coll, 'children'));
        })
        .flatten()
        .find(search);
}

A little JSfiddle.

4 个答案:

答案 0 :(得分:2)

您需要递归调用该函数才能定位子对象。尝试关注

遍历数组,并为每个对象检查是否找到id。如果是,则中断并返回结果,否则继续在child(如果存在)中进行搜索。

方法1:遍历树枝

使用这种方法,代码首先遍历第一个元素,直到最后一个孩子,然后遍历第二个元素,最后一个孩子,依此类推。

var objects = [{id: 1,name: 'foo'}, {id: 2,name: 'bar',childs: [{id: 3,name: 'baz',childs: [{id: 4,name: 'foobar'}]}]}];

function findObject(arr, id) {
  var result;
  for (let i = 0 ; i < arr.length; i++) {
    if(arr[i].id === id) {
      result = arr[i];
      break;
    }
    if(arr[i].childs) {
      result = findObject(arr[i].childs, id);
      if(result) break;
    }
  }
  return result;
}

console.log(findObject(objects, 4));

方法2:按深度遍历树的深度

使用这种方法,首先遍历第一级元素,然后遍历第二级元素,依此类推。

var objects = [{id: 1,name: 'foo'}, {id: 2,name: 'bar',childs: [{id: 3,name: 'baz',childs: [{id: 4,name: 'foobar'}]}]}];

function findObject(arr, id) {
  var result;
  var children = [];
  for (let i = 0 ; i < arr.length; i++) {
    if(arr[i].id === id) {
      result = arr[i];
      break;
    }
    if(arr[i].childs) {
      children = [...children, ...arr[i].childs];
    }
  }
  if(!result && children.length) {
    result = findObject(children, id);
  }
  return result;
}

console.log(findObject(objects, 4));

答案 1 :(得分:2)

您可以采用迭代和递归的方法。

function find(id, array) {
    var result;
    array.some(o => o.id === id && (result = o) || (result = find(id, o.children || [])));
    return result;
}

var objects = [{ id: 1, name: 'foo' }, { id: 2, name: 'bar', children: [{ id: 3, name: 'baz', children: [{ id: 4, name: 'foobar' }] }] }];

console.log(find(1, objects));
console.log(find(2, objects));
console.log(find(3, objects));
console.log(find(4, objects));
.as-console-wrapper { max-height: 100% !important; top: 0; }

答案 2 :(得分:1)

您可以像这样递归地进行操作:

function deepFind(arr, search) {
    for(var obj of arr) {
        if(search(obj)) {
            return obj;
        }
        if(obj.childs) {
            var deepResult = deepFind(obj.childs, search);
            if(deepResult) {
                return deepResult;
            }
        }
    }
    return null;
}

然后像这样使用它:

var result = deepFind(objects, function(obj) {
    return obj.id === myId;
});

示例:

function deepFind(arr, search) {
    for(var obj of arr) {
        if(search(obj)) {
            return obj;
        }
        if(obj.childs) {
            var deepResult = deepFind(obj.childs, search);
            if(deepResult) {
                return deepResult;
            }
        }
    }
    return null;
}

var objects = [{id: 1,name: 'foo'}, {id: 2,name: 'bar',childs: [{id: 3,name: 'baz',childs: [{id: 4,name: 'foobar'}]}]}];

console.log("ID 1:", deepFind(objects, obj => obj.id === 1));
console.log("ID 4:", deepFind(objects, obj => obj.id === 4));
console.log("ID 7:", deepFind(objects, obj => obj.id === 7));

答案 3 :(得分:0)

您可以使用递归功能并检查孩子

var objects = [{
  id: 1,
  name: 'foo'
}, {
  id: 2,
  name: 'bar',
  childs: [{
    id: 3,
    name: 'baz',
    childs: [{
      id: 4,
      name: 'foobar'
    }]
  }]
}];
let tempArray = [];


function doRecursiveSearch(obj, id) {

  obj.forEach(function(item) {
    console.log(item)
    if (item.id === id) {
      tempArray.push(item)
    } else {
      if (item.childs && Array.isArray(item.childs)) {
        console.log(item)
        doRecursiveSearch(item.childs, id)
      }
    }

  })
}
doRecursiveSearch(objects, 4)
console.log(tempArray)