【问题标题】:Find an object in an array of deeply nested objects recursively递归查找深度嵌套对象数组中的对象
【发布时间】:2018-02-14 05:19:15
【问题描述】:

我有一个数组,每个项目都是一个具有唯一 ID 的对象。有些项目也可能有孩子,它可以在孩子数组中包含孩子数组。我正在尝试使用 Id 选择一个项目。

           const array = [
                {
                    uuid: '40E75F3DE56B4B11B3AFBDE46785737B'
                }, {
                    uuid: '9CEF74766BBB4B9682B7817B43CEAE48'
                }, {
                    uuid: '34F209A883D3406FBA6BACD9E07DB1D9',
                    children: [{
                        uuid: 'F429C51BF01C405DA517616E0E16DE4E',
                        children: [{
                            uuid: '8823CFCE7D4645C68991332091C1A05C'
                        }, {
                            uuid: '58A9345E881F48C980498C7FFB68667D'
                        }]
                    }]
                }, {
                    uuid: '152488CC33434A8C9CACBC2E06A7E535'
                }, {
                    uuid: '9152B3DEF40F414BBBC68CACE2F5F6E4'
                }, {
                    uuid: 'B9A39766B17E4406864D785DB6893C3D'
                },
                {
                    uuid: '3J4H4J5HN6K4344D785DBJ345HSSODF',
                    children: [
                        {
                            uuid: 'EAB14DD72DA24BB88B4837C9D5276859'
                        },
                        {
                            uuid: 'FFA80D043380481F8835859A0839512B'
                        },
                        {
                            uuid: '9679687190354FA79EB9D1CA7B4962B1'
                        }
                    ]
                }
            ]

下面的代码适用于没有子元素的简单数组。我需要一个函数,或者一个 lodash 模块,它可以递归地搜索整个数组并返回对象(数组中的项)

findContainingObject(array, uuid) {
    let result = [];
    result = array.filter( item => {
        return item.uuid === uuid
    })
    return result;
}

预期输出:

findContainingObject(array, '40E75F3DE56B4B11B3AFBDE46785737B')

               {
                 uuid: '40E75F3DE56B4B11B3AFBDE46785737B'
               }

findContainingObject(array, '34F209A883D3406FBA6BACD9E07DB1D9')
                {
                    uuid: '34F209A883D3406FBA6BACD9E07DB1D9',
                    children: [{
                        uuid: 'F429C51BF01C405DA517616E0E16DE4E',
                        children: [{
                            uuid: '8823CFCE7D4645C68991332091C1A05C'
                        }, {
                            uuid: '58A9345E881F48C980498C7FFB68667D'
                        }]
                    }]
                }

findContainingObject(array, '58A9345E881F48C980498C7FFB68667D')

                 {
                    uuid: '58A9345E881F48C980498C7FFB68667D'
                 }

【问题讨论】:

    标签: javascript arrays recursion lodash


    【解决方案1】:

    这个函数实现了DFS:

    function findDFS(objects, id) {
      for (let o of objects || []) {
        if (o.uuid == id) return o
        const o_ = findDFS(o.children, id)
        if (o_) return o_
      }
    }
    

    和 BFS:

    function findBFS(objects, id) {
      const queue = [...objects]
      while (queue.length) {
        const o = queue.shift()
        if (o.uuid == id) return o
        queue.push(...(o.children || []))
      }
    }
    

    【讨论】:

    • 感谢您的解决方案。我走的是同一条路线,但如果我必须查找“B9A39766B17E4406864D785DB6893C3D”,不会很贵?
    • @VamshiGudipati 是的,会很贵。原始数组来自哪里?服务器端API?数据库?你可以访问它吗?
    • 这是我们创建的拖放界面的输出,我无法控制传入的数据。我正在编写一个编译器来将这些数据转换为另一种形式的数据
    • @VamshiGudipati,如果您事先不知道具有给定 ID 的对象的大致位置,它总是会“昂贵”。这个find 函数是 DFS。如果您通常希望您的用户在第一级搜索对象,那么您需要实现 BFS。
    • 非常感谢您的详细解释。我真的很感激!
    【解决方案2】:

    这是一个类似的答案,更多的代码行可能更好的可读性。

    const array = [
      {
          uuid: '40E75F3DE56B4B11B3AFBDE46785737B'
      }, {
          uuid: '9CEF74766BBB4B9682B7817B43CEAE48'
      }, {
          uuid: '34F209A883D3406FBA6BACD9E07DB1D9',
          children: [{
              uuid: 'F429C51BF01C405DA517616E0E16DE4E',
              children: [{
                  uuid: '8823CFCE7D4645C68991332091C1A05C'
              }, {
                  uuid: '58A9345E881F48C980498C7FFB68667D'
              }]
          }]
      }, {
          uuid: '152488CC33434A8C9CACBC2E06A7E535'
      }, {
          uuid: '9152B3DEF40F414BBBC68CACE2F5F6E4'
      }, {
          uuid: 'B9A39766B17E4406864D785DB6893C3D'
      },
      {
          uuid: '3J4H4J5HN6K4344D785DBJ345HSSODF',
          children: [
              {
                  uuid: 'EAB14DD72DA24BB88B4837C9D5276859'
              },
              {
                  uuid: 'FFA80D043380481F8835859A0839512B'
              },
              {
                  uuid: '9679687190354FA79EB9D1CA7B4962B1'
              }
          ]
      }
      ];
      
      
    function findContainingObject(array, itemId) {
      let
        index = 0,
        result = null;
        
      while (index < array.length && !result) {
        const
          item = array[index];
          
        if (item.uuid === itemId) {
          result = item;
        } else if (item.children !== undefined) {
          result = findContainingObject(item.children, itemId);
        }
        
        if (result === null) {
          index++;
        }
      }
      
      return result;
    }
    
    console.log(findContainingObject(array, '40E75F3DE56B4B11B3AFBDE46785737B'));
    console.log(findContainingObject(array, '34F209A883D3406FBA6BACD9E07DB1D9'));
    console.log(findContainingObject(array, '58A9345E881F48C980498C7FFB68667D'));

    【讨论】:

      【解决方案3】:

      使用递归的示例。

      const data = [{
          uuid: '40E75F3DE56B4B11B3AFBDE46785737B'
        }, {
          uuid: '9CEF74766BBB4B9682B7817B43CEAE48'
        }, {
          uuid: '34F209A883D3406FBA6BACD9E07DB1D9',
          children: [{
            uuid: 'F429C51BF01C405DA517616E0E16DE4E',
            children: [{
              uuid: '8823CFCE7D4645C68991332091C1A05C'
            }, {
              uuid: '58A9345E881F48C980498C7FFB68667D'
            }]
          }]
        }, {
          uuid: '152488CC33434A8C9CACBC2E06A7E535'
        }, {
          uuid: '9152B3DEF40F414BBBC68CACE2F5F6E4'
        }, {
          uuid: 'B9A39766B17E4406864D785DB6893C3D'
        },
        {
          uuid: '3J4H4J5HN6K4344D785DBJ345HSSODF',
          children: [{
              uuid: 'EAB14DD72DA24BB88B4837C9D5276859'
            },
            {
              uuid: 'FFA80D043380481F8835859A0839512B'
            },
            {
              uuid: '9679687190354FA79EB9D1CA7B4962B1'
            }
          ]
        }
      ];
      
      let find = (data, uuid) => {
        for (let o of data) {
          if (o.uuid === uuid) {
            return o;
          };
          if ('children' in o) {
            let ro = find(o.children, uuid);
            if (ro) {
              return ro;
            }
          }
        }
      }
      
      let result = find(data, '9679687190354FA79EB9D1CA7B4962B1')
      console.clear();
      console.log(result);

      【讨论】:

      • 顺便说一下,@skovorodkin 的回答在我看来是最完整的 +1 :)
      猜你喜欢
      • 2021-08-10
      • 1970-01-01
      • 1970-01-01
      • 2018-03-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2023-01-13
      • 1970-01-01
      相关资源
      最近更新 更多