我想要实现的目标: 例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'
}
}
}
}
我正在努力寻找一种高性能的方法来做到这一点,而无需创建新的对象或数组,只需使用迭代和递归。
感谢您的帮助
答案 0 :(得分:0)
您遇到的问题是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>');