我有一个2D数组,表示这种格式的树:
[["Food", 0], ["Dairy", 1], ["Milk", 2], ["Low-fat", 3], ["Butter", 2], ["Cheese", 2], ["Vegetables", 1], ["Spinach", 2], ["Meat", 1], ["Fish", 2], ["Salmon", 3], ["Poultry", 2]]
每个项目(节点)都是一个数组,其第一个元素是名称,第二个是节点的级别(深度)。
我需要将这个2D数组转换为嵌套的JavaScript对象,其中每个节点对象由name(字符串)和children(对象数组)组成。结果应该是根对象(此处为“Food”),其他所有项目都是其子项。输入数组将始终排序,因此可以假设第一个元素是root。
通过迭代或递归,最好的方法是什么?
答案 0 :(得分:2)
没有必要进行递归。我认为这就是你要找的东西:
function tree_from_list(list) {
var list_node = list.shift();
var depth = list_node[1];
var root = {name: list_node[0], children: []};
var tree_node;
var cur_nodes = [];
cur_nodes[depth] = root;
while (list.length > 0) {
list_node = list.shift();
tree_node = {name: list_node[0], children: []};
depth = list_node[1];
if (cur_nodes[depth - 1] === undefined)
throw 'invalid list!';
cur_nodes[depth - 1].children.push(tree_node);
cur_nodes[depth] = tree_node;
}
return root;
}
var list = [["Food", 0], ["Dairy", 1], ["Milk", 2], ["Low-fat", 3], ["Butter", 2], ["Cheese", 2], ["Vegetables", 1], ["Spinach", 2], ["Meat", 1], ["Fish", 2], ["Salmon", 3], ["Poultry", 2]];
var tree = tree_from_list(list);
答案 1 :(得分:0)
这是一个无意义(效率较低)的递归解决方案:
function mktree(lis, lvl) {
var i, el, c, itemlis = [];
for (i = 0; el = lis[i++];) {
if (lvl !== el[1])
break;
var item = {};
[item[el[0]], c] = mktree(lis.slice(i), lvl + 1);
i += c - 1; // skip ahead
itemlis.push(item);
}
return [itemlis, i];
}
function lis_to_tree(arr) {
return mktree(arr, 0, 0)[0][0];
}
var arr = [["Food", 0], ["Dairy", 1], ["Milk", 2], ["Low-fat", 3], ["2%", 3],
["Butter", 2], ["Cheese", 2], ["Vegetables", 1], ["Spinach", 2],
["Meat", 1], ["Fish", 2], ["Salmon", 3], ["Poultry", 2]];
var tree = lis_to_tree(arr);
(请注意,这取决于解构分配以跳过已经处理过的元素。您可以删除此功能,但速度要慢得多。)
我称之为毫无意义,因为它本质上试图模仿迭代,它维护已经处理过的元素计数,因此它可以在列表中向前跳过。我并不是说完全无用,因为我仍然发现递归版本比迭代版本更容易阅读。