代码之家  ›  专栏  ›  技术社区  ›  mr__brainwash

在嵌套对象数组中按属性路径查找对象

  •  3
  • mr__brainwash  · 技术社区  · 7 年前

    我有这样的目标:

    var obj = [
        {
          name: 'ob_1',
          childFields: [],
        },
        {
          name: 'ob_2',
          childFields: [
            {
              name: 'ob_2_1',
              childFields: [
                {
                  name: 'ob_3_1',
                  childFields: [],
                  test: 124
                },
              ],
            },
          ],
        },
      ]
    
    function getObjectByNamePath(path, fieds) {
        const pathArr = path.split('.');
        const result = fieds.find(field => {
          if (pathArr.length > 1) {
            if (field.name === pathArr[0] && field.childFields.length) {
              const newPath = pathArr.slice(1, pathArr.length).join('.');
              return getObjectByNamePath(newPath, field.childFields);
            }
            return false;
          } else {
            if (field.name === pathArr[0]) {
                return true;
            } else {
                return false;
            }
          }
        });
        return result;
      }
    

    我要按名称值获取对象路径:

    console.log(getObjectByNamePath('ob_2.ob_2_1.ob_3_1', obj))
    

    我试过了 this ,但它不起作用,我觉得有更优雅的方式来实现我想要的。谢谢。

    2 回复  |  直到 7 年前
        1
  •  5
  •   Nina Scholz    7 年前

    你可以迭代 childFields 找到 name 对于此级别,则采用下一个级别名称。

    function getObjectByNamePath(path, array) {
        return path
            .split('.')
            .reduce(
                ({ childFields = [] } = {}, name) => childFields.find(o => o.name === name),
                { childFields: array }
            );
    }
    
    var obj = [{ name: 'ob_1', childFields: [], }, { name: 'ob_2', childFields: [ { name: 'ob_2_1', childFields: [ { name: 'ob_3_1', childFields: [], test: 124 }] }] }];
    
    console.log(getObjectByNamePath('ob_2.ob_2_1.ob_3_1', obj));
    console.log(getObjectByNamePath('ob_1', obj));
    console.log(getObjectByNamePath('foo.bar', obj));
    .as-console-wrapper { max-height: 100% !important; top: 0; }
        2
  •  1
  •   Ritwick Dey    7 年前

    递归解。

    var obj = [{ name: 'ob_1', childFields: [], }, { name: 'ob_2', childFields: [ { name: 'ob_2_1', childFields: [ { name: 'ob_3_1', childFields: [], test: 124 }] }] }]
    
    function getObjectByNamePath(path, obj) {
      const [currentPath, ...restPaths] = path.split('.'); 
      const nextObj = (obj.find(e => e.name === currentPath))
      
      if(!restPaths.length) return nextObj;
      return getObjectByNamePath(restPaths.join('.'), nextObj.childFields || []);
    }
    
    
    // Test Cases
    console.log(getObjectByNamePath('ob_2.ob_2_1.ob_3_1', obj))
    console.log(getObjectByNamePath('ob_2.ob_2_1.ob_3_1.fakePath', obj))
    console.log(getObjectByNamePath('ob_1', obj))
    console.log(getObjectByNamePath('', obj))