【问题标题】:tree to depthTree conversion树到深度树的转换
【发布时间】:2016-02-20 11:48:19
【问题描述】:

我想要实现的示例: 示例 1

var input = { // depth of tree is 1
  a: 'a'
}

expect(toDepthTree(input)).to.deep.equal(output)

var output = {
  1: { // 1 equals to depth of input
    a: 'a'
  }
}

示例 2:

var input = { // depth of tree is 2
  a: {
    b: 'b'
  }
}

expect(toDepthTree(input)).to.equal(output)

var output = {
  2: { // 2 equals to depth of input
    a: {
      b: 'b'
    }    
  }
}

这些是更容易理解问题的介绍性示例。这是失败的实际测试:

it('should return depth tree if normal tree is provided', () => {
  const input = {
    a1: {
      b1: {
        c1: {
          d1: 'd1',
          d2: 'd2'
        },
        c2: {
          d3: 'd3'
        }
      },
      b2: {
        c3: 'c3'
      }
    },
    a2: {
      b3: 'b3'
    },
    a3: 'a3'
  }
  const output = {
    1: {
      a3: 'a3'
    },
    2: {
      a2: {
        b3: 'b3'
      }
    },
    3: {
      a1: {
        b1: {
          c2: {
            d3: 'd3'
          }
        }
      }
    }
    4: {
      a1: {
        b1: {
          c1: {
            d1: 'd1',
            d2: 'd2'
          }
        },
        b2: {
          c3: 'c3'
        }
      }
    }
  }
  expect(toLengthTree(input)).to.deep.equal(output)
})

我有以下代码来执行树遍历和返回值:

function depthOf(tree) {
  let level = 1
  for (const key in tree) {
    if (!tree.hasOwnProperty(key)) continue
    if (tree[key] && tree[key].constructor === Object) {
      const depth = depthOf(tree[key]) + 1
      level = Math.max(depth, level) // this is a problem
    }
  }
  return level
}

function* iterateTree(tree) {
  for (const key in tree) {
    if (tree.hasOwnProperty(key)) {
      const value = { [key]: tree[key] }
      yield { value, depth: depthOf(value) }
    }
  }
}

export function toDepthTree(tree) {
  const result = {}
  for (const { value, depth } of iterateTree(tree)) {
    if (!result[depth]) {
      result[depth] = {}
    }
    result[depth] = {
      ...result[depth],
      ...value
    }
  }
  return result
}

但是最后一次测试失败了,因为我得到了一个键的最大深度,因此我得到的结果是:

  const output = {
    1: {
      a3: 'a3'
    },
    2: {
      a2: {
        b3: 'b3'
      }
    },
    4: { // notice no 3: { ... } here, but it should be
      a1: {
        b1: {
          c1: {
            d1: 'd1',
            d2: 'd2'
          },
          c2: {
            d3: 'd3'
          }
        },
        b2: {
          c3: 'c3'
        }
      }
    }
  }

我正在努力寻找一种高性能的方法来做到这一点,而无需创建新的对象或数组,而只使用迭代和递归。

感谢您的帮助

【问题讨论】:

    标签: javascript object tree traversal tree-traversal


    【解决方案1】:

    您遇到的问题是 depth-first search 然后停止迭代。在这种情况下,您只能得到 4 的深度,而不是 3 的深度。

    也许这会有所帮助,它会在到达树的末尾时覆盖结果集。

    function go(o, base, l) {
        if (typeof o === 'object') {
            Object.keys(o).forEach(function (k) {
                return go(o[k], base, l + 1);
            });
        } else {
            result[l] = base;
        }
    }
    
    var input = { a1: { b1: { c1: { d1: 'd1', d2: 'd2' }, c2: { d3: 'd3' } }, b2: { c3: 'c3' } }, a2: { b3: 'b3' }, a3: 'a3' },
        result = {};
    
    Object.keys(input).forEach(function (k) {
        return go(input[k], input[k], 1);
    });
    
    document.write('<pre>' + JSON.stringify(result, 0, 4) + '</pre>');

    【讨论】:

      猜你喜欢
      • 2017-07-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-13
      • 2017-03-07
      相关资源
      最近更新 更多