JavaScript树 - 优雅的解决方案?

时间:2012-02-17 09:39:17

标签: javascript tree

我有多棵树,例如:

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)。

我想构建两件事:

  1. 所有根的数组。在此示例中:['a', 'h']

  2. 对于每个根,包含所有后代的数组,包括根。在这个例子中:

    ['a', 'b', 'c', 'd', 'e', 'f', 'g']

    ['h', 'i', 'j', 'k', 'l', 'm', 'n']

  3. 结果数组中元素的顺序无关紧要。

    你能否建议一种优雅的方法在JavaScript中实现它(允许jQuery)。

2 个答案:

答案 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);