How to find a object in a nested array using recursion in JS

后端 未结 7 829
慢半拍i
慢半拍i 2021-01-04 21:58

Consider the following deeply nested array:

const array = [
    {
        id: 1,
        name: \"bla\",
        children: [
            {
                id:         


        
相关标签:
7条回答
  • 2021-01-04 22:06

    You need to iterate through your objects and then need to be parse each object using recursion. Try the answer mentioned here: JavaScript recursive search in JSON object

    code:

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

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

    }`

    0 讨论(0)
  • 2021-01-04 22:09

    You can do:

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

    0 讨论(0)
  • 2021-01-04 22:10

    This will use recursive find by level, it'll try to find the item in array and then call itself with the children of each item in the array:

    New browsers will have Array.prototype.flatten but in this case I've added the flatten function separately.

    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({}));

    0 讨论(0)
  • 2021-01-04 22:10

    We use object-scan for most of our data processing. It's awesome for all sorts of things, but does take a while to wrap your head around. This is how one could answer your question:

    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
    
    0 讨论(0)
  • 2021-01-04 22:16

    You might use a recursive reduce:

    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, item) => {
        if (a) return a;
        if (item.id === itemId) return item;
        if (item[nestingKey]) return findItemNested(item[nestingKey], itemId, nestingKey)
      }, null)
    );
    const res = findItemNested(array, 959, "children");
    console.log(res);

    0 讨论(0)
  • 2021-01-04 22:17

    You might also use recursion with Array.find like below

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

    0 讨论(0)
提交回复
热议问题