我有多棵树,例如:
a h
| \ |
b c i
/ | \ / \
d e f j k
| / | \
g l m n
在单个JavaScript对象中表示如下:
{ 'a': ['b', 'c'],
'b': null,
'c': ['d', 'e', 'f'],
'd': null,
'e': ['g'],
'f': null,
'g': null,
'h': ['i'],
'i': ['j', 'k'],
'j': ['l', 'm', 'n'],
'k': null,
'l': null,
'm': null,
'n': null }
即。所有节点都显示为键,特定键/节点的值是其所有子节点的数组(如果没有子节点,则为null
)。
我想构建两件事:
所有根的数组。在此示例中:['a', 'h']
对于每个根,包含所有后代的数组,包括根。在这个例子中:
['a', 'b', 'c', 'd', 'e', 'f', 'g']
['h', 'i', 'j', 'k', 'l', 'm', 'n']
结果数组中元素的顺序无关紧要。
你能否建议一种优雅的方法在JavaScript中实现它(允许jQuery)。
答案 0 :(得分:1)
var src = { 'a': ['b', 'c'],
'b': null,
'c': ['d', 'e', 'f'],
'd': null,
'e': ['g'],
'f': null,
'g': null,
'h': ['i'],
'i': ['j', 'k'],
'j': ['l', 'm', 'n'],
'k': null,
'l': null,
'm': null,
'n': null };
/* ******************************************************************* */
var roots={},p1,p2,isRoot,i=-1;
for(p1 in src){
isRoot=true;
for(p2 in src)if(src[p2]&&src[p2].indexOf(p1)>-1){isRoot=false;break;}
if(isRoot)roots[p1]=[p1];
}
for(p1 in roots){
i=-1;
while(++i<roots[p1].length)
if(src[roots[p1][i]]&&src[roots[p1][i]].length)
Array.prototype.push.apply(roots[p1],src[roots[p1][i]]);
}
因此roots
变量包含第二个任务的下一个值:
roots: {
"a": ["a", "b", "c", "d", "e", "f", "g"],
"h": ["h", "i", "j", "k", "l", "m", "n"]
}
对于您的第一个任务Object.keys(roots)
返回所需的数组。
答案 1 :(得分:0)
var tree = {...};
var roots = [], rootdescendants = {};
tl: for (var p in tree) { // tree-loop
for (var r in rootdescendants)
// check if p is already in one of the result arrays
if (rootdescendants[r].lastIndexOf(p)>-1)
continue tl;
var d = rootdescendants[p] = [p]; // create new descendants array
for (var i=0; i<d.length; i++) {
var c = d[i];
if (i>0 && c in rootdescendants) { // there is already an array for c
i += rootdescendants[c].unshift(i, 1) - 3;
Array.prototype.splice.apply(d, rootdescendants[c]); // insert into d
delete rootdescendants[c];
} else {
if (tree[c]) // not null
Array.prototype.push.apply(d, tree[c]);
}
}
}
roots = Object.keys(rootdescendants);