如何在JS中使用递归在嵌套数组中查找对象

时间:2018-11-20 09:59:28

标签: javascript recursion nested

考虑以下深度嵌套的数组:

const array = [
    {
        id: 1,
        name: "bla",
        children: [
            {
                id: 23,
                name: "bla",
                children: [{ id: 88, name: "bla" }, { id: 99, name: "bla" }]
            },
            { id: 43, name: "bla" },
            {
                id: 45,
                name: "bla",
                children: [{ id: 43, name: "bla" }, { id: 46, name: "bla" }]
            }
        ]
    },
    {
        id: 12,
        name: "bla",
        children: [
            {
                id: 232,
                name: "bla",
                children: [{ id: 848, name: "bla" }, { id: 959, name: "bla" }]
            },
            { id: 433, name: "bla" },
            {
                id: 445,
                name: "bla",
                children: [
                    { id: 443, name: "bla" },
                    {
                        id: 456,
                        name: "bla",
                        children: [
                            {
                                id: 97,
                                name: "bla"
                            },
                            {
                                id: 56,
                                name: "bla"
                            }
                        ]
                    }
                ]
            }
        ]
    },
    {
        id: 15,
        name: "bla",
        children: [
            {
                id: 263,
                name: "bla",
                children: [{ id: 868, name: "bla" }, { id: 979, name: "bla" }]
            },
            { id: 483, name: "bla" },
            {
                id: 445,
                name: "bla",
                children: [{ id: 423, name: "bla" }, { id: 436, name: "bla" }]
            }
        ]
    }
];

我如何使用递归通过可能深深嵌套的键来抓取某个对象? 我已经尝试过了,但是这不适用于嵌套超过2个级别的情况,它只会返回undefined

const findItemNested = (arr, itemId, nestingKey) => {
    for (const i of arr) {
        console.log(i.id);
        if (i.id === itemId) {
            return i;
        }
        if (i[nestingKey]) {
            findItemNested(i[nestingKey], itemId, nestingKey);
        }
    }
};

结果应为:

const res = findItemNested(array, 959, "children"); >> { id: 959, name: "bla" }

这也许也可以使用.find来实现,或者仅通过(子元素键)展平数组来实现,但是对我来说,使用递归似乎是最合乎逻辑的解决方案。有人对此有解决方案吗?

预先感谢:)。

7 个答案:

答案 0 :(得分:5)

您可以使用递归ConsoleProfiler.exe xmlfile <path_to_config> --save-to=<path_to_snapshot>

reduce

答案 1 :(得分:2)

您还可以将递归与Array.find一起使用,如下所示

const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];


function findById(arr, id, nestingKey) {
  
  // if empty array then return
  if(arr.length == 0) return
  
  // return element if found else collect all children(or other nestedKey) array and run this function
  return arr.find(d => d.id == id) 
      || findById(arr.flatMap(d => d[nestingKey] || []), id) 
      || 'Not found'
}

console.log(findById(array, 12, 'children'))

console.log(findById(array, 483, 'children'))

console.log(findById(array, 1200, 'children'))

答案 2 :(得分:0)

这应该有效:

function findByIdRecursive(array, id) {
  for (let index = 0; index < array.length; index++) {
    const element = array[index];
    if (element.id === id) {
      return element;
    } else {
      if (element.children) {
        const found = findByIdRecursive(element.children, id);

        if (found) {
          return found;
        }
      }
    }
  }
}

答案 3 :(得分:0)

您可以这样做:

const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];
const findItemNested = (arr, itemId, nestingKey) => arr.reduce((a, c) => {
  return a.length
    ? a
    : c.id === itemId
      ? a.concat(c)
      : c[nestingKey]
        ? a.concat(findItemNested(c[nestingKey], itemId, nestingKey))
        : a
}, []);
const res = findItemNested(array, 959, "children");

if (res.length) {
  console.log(res[0]);
}

答案 4 :(得分:0)

这将按级别使用递归查找,它将尝试在数组中查找该项目,然后使用数组中每个项目的子项进行自身调用:

新的浏览器将具有Array.prototype.flatten,但在这种情况下,我已单独添加了flatten函数。

const array = [{"id":1,"name":"bla","children":[{"id":23,"name":"bla","children":[{"id":88,"name":"bla"},{"id":99,"name":"bla"}]},{"id":43,"name":"bla"},{"id":45,"name":"bla","children":[{"id":43,"name":"bla"},{"id":46,"name":"bla"}]}]},{"id":12,"name":"bla","children":[{"id":232,"name":"bla","children":[{"id":848,"name":"bla"},{"id":959,"name":"bla"}]},{"id":433,"name":"bla"},{"id":445,"name":"bla","children":[{"id":443,"name":"bla"},{"id":456,"name":"bla","children":[{"id":97,"name":"bla"},{"id":56,"name":"bla"}]}]}]},{"id":15,"name":"bla","children":[{"id":263,"name":"bla","children":[{"id":868,"name":"bla"},{"id":979,"name":"bla"}]},{"id":483,"name":"bla"},{"id":445,"name":"bla","children":[{"id":423,"name":"bla"},{"id":436,"name":"bla"}]}]}];


const flatten = (arr) =>
  arr.reduce((result, item) => result.concat(item), []);
const findBy = (findFunction, subItemsKey) => (array) =>
  //array is empty (can be when children of children of children does not exist)
  array.length === 0
    ? undefined //return undefined when array is empty
    : array.find(findFunction) || //return item if found
      findBy(findFunction, subItemsKey)(//call itself when item is not found
        flatten(
          //take children from each item and flatten it
          //([[child],[child,child]])=>[child,child,child]
          array.map((item) => item[subItemsKey] || []),
        ),
      );
const findChildrenById = (array) => (value) =>
  findBy((item) => item.id === value, 'children')(array);
const findInArray = findChildrenById(array);

console.log('found', findInArray(99));
console.log('not found', findInArray({}));

答案 5 :(得分:0)

我们使用object-scan进行大多数数据处理。它对各种各样的事情都很棒,但是确实需要花费一些时间。这样可以回答您的问题:

const objectScan = require('object-scan');

const find = (data, id) => objectScan(['**(^children$).id'], {
  abort: true,
  rtn: 'parent',
  useArraySelector: false,
  filterFn: ({ value }) => value === id
})(data);

const array=[{id:1,name:"bla",children:[{id:23,name:"bla",children:[{id:88,name:"bla"},{id:99,name:"bla"}]},{id:43,name:"bla"},{id:45,name:"bla",children:[{id:43,name:"bla"},{id:46,name:"bla"}]}]},{id:12,name:"bla",children:[{id:232,name:"bla",children:[{id:848,name:"bla"},{id:959,name:"bla"}]},{id:433,name:"bla"},{id:445,name:"bla",children:[{id:443,name:"bla"},{id:456,name:"bla",children:[{id:97,name:"bla"},{id:56,name:"bla"}]}]}]},{id:15,name:"bla",children:[{id:263,name:"bla",children:[{id:868,name:"bla"},{id:979,name:"bla"}]},{id:483,name:"bla"},{id:445,name:"bla",children:[{id:423,name:"bla"},{id:436,name:"bla"}]}]}];

console.log(find(array, 12));
// => { id: 12, name: 'bla', children: [ { id: 232, name: 'bla', children: [Array] }, { id: 433, name: 'bla' }, { id: 445, name: 'bla', children: [Array] } ] }
console.log(find(array, 483));
// => { id: 483, name: 'bla' }
console.log(find(array, 959));
// => { id: 959, name: 'bla' }
console.log(find(array, 1200));
// => undefined

答案 6 :(得分:-2)

您需要遍历对象,然后需要使用递归解析每个对象。试试这里提到的答案:JavaScript recursive search in JSON object

代码:

`function findNode(id,currentNode){     var i,         currentChild,         结果;

if (id == currentNode.id) {
    return currentNode;
} else {

    // Use a for loop instead of forEach to avoid nested functions
    // Otherwise "return" will not work properly
    for (i = 0; i < currentNode.children.length; i += 1) {
        currentChild = currentNode.children[i];

        // Search in the current child
        result = findNode(id, currentChild);

        // Return the result if the node has been found
        if (result !== false) {
            return result;
        }
    }

    // The node has not been found and we have no more options
    return false;
}

}`