从js数组创建树

时间:2016-05-20 15:49:46

标签: javascript java tree

我正在尝试从列表中创建树。我的数据就像;

A-->B-->C-->D-->E..
A-->B-->C-->D-->F..
A-->F-->C-->D-->E..
.
.
.

我在数组中有所有可能的数据路径。我希望像

一样显示它
                     A
                       -B
                         -C
                           -D 
                              -E
                              -F
                       -F
                         -C
                           -D
                             -E 

如何使用javascript创建和检查?我需要createTreeFunction:)

function parseData(data)
  {


   $.each(data, function (i, p) {
                   var arr = p.split("--->");

                 createTreeFunction(p);

                  });

   };
  function parseData(data)
      {


       $.each(data, function (i, p) {
                       var arr = p.split("--->");

                     createTreeFunction(p);

                      });

   };

2 个答案:

答案 0 :(得分:3)

基本上,您可以为子项使用至少两种不同的结构来构建树,一种使用数组(解决方案A)或使用对象(解决方案B)。

数组优于对象的优点是直接迭代子对象。使用对象,您需要先获取键,然后才能进行迭代。

否则,如果您知道一个孩子,那么通过密钥的访问速度会更快。将新节点插入树中也是如此。

使用子数组,您需要一个函数getChild来测试孩子是否存在。

注意,提供的数据不会使标识符保持唯一。

包含儿童数组的解决方案A:

function Node(id) {
    this.id = id;
    this.children = []; // array
}

Node.prototype.getChild = function (id) {
    var node;
    this.children.some(function (n) {
        if (n.id === id) {
            node = n;
            return true;
        }
    });
    return node;
};

var path = ['A-->B-->C-->D-->E', 'A-->B-->C-->D-->F', 'A-->F-->C-->D-->E'],
    tree = new Node('root');

path.forEach(function (a) {
    var parts = a.split('-->');
    parts.reduce(function (r, b) {
        var node = r.getChild(b);
        if (!node) {
            node = new Node(b);
            r.children.push(node);
        }
        return node;
    }, tree);
});

document.getElementById('out').innerHTML = JSON.stringify(tree, 0, 4);
<pre id="out"></pre>

包含儿童对象的解决方案B:

function Node(id) {
    this.id = id;
    this.children = {}; // object
}

var path = ['A-->B-->C-->D-->E', 'A-->B-->C-->D-->F', 'A-->F-->C-->D-->E'],
    tree = new Node('root');

path.forEach(function (a) {
    var parts = a.split('-->');
    parts.reduce(function (r, b) {
        if (!r.children[b]) {
            r.children[b] = new Node(b);
        }
        return r.children[b];
    }, tree);
});

document.getElementById('out').innerHTML = JSON.stringify(tree, 0, 4);
<pre id="out"></pre>

两个提案都使用Array#forEachArray#reduce来迭代给定的字符串,并将引用返回给实际的id。如果未找到id,则会获取新的节点实例并将其添加到数组或对象中。将返回引用以进行下一次ID检查。

答案 1 :(得分:0)

对于这个用例,我发明了非常有用的两个Object方法;即Object.prototype.getNestedValue()Object.prototype.setNestedValue()。通过利用这些方法,这项工作只不过是一个单线程JS代码。见下文......

Object.prototype.getNestedValue = function(...a) {
  return a.length > 1 ? (this[a[0]] !== void 0 && this[a[0]].getNestedValue(...a.slice(1))) : this[a[0]];
};
Object.prototype.setNestedValue = function(...a) {
  return a.length > 2 ? typeof this[a[0]] === "object" && this[a[0]] !== null ? this[a[0]].setNestedValue(...a.slice(1))
                                                                              : (this[a[0]] = typeof a[1] === "string" ? {} : new Array(a[1]),
                                                                                 this[a[0]].setNestedValue(...a.slice(1)))
                      : this[a[0]] = a[1];
};

var data = "A-->B-->C-->D-->E\nA-->B-->C-->D-->F\nA-->F-->C-->D-->E",
  datarr = data.split("\n").map(e => e.split("-->")), // get your list in an array
       o = {};
datarr.forEach(a => !o.getNestedValue(...a) && o.setNestedValue(...a,null));

console.log(JSON.stringify(o,null,2));