注意:下面的解决方案!
问题: 我需要代码将具有id和parent值的平面对象数组转换为树。由于平面数组是动态生成的,因此深度级别的数量是未知的。
此外,一旦项目在树中,我需要为节点分配一个级别属性值,具体取决于它们所在的树级别(根节点=级别0,根的直接子节点=级别1,子节点孩子= 2级等)。
最后,每个树级别的节点应按其ID进行alpha排序。所以应该对root id进行排序,然后根据孩子,然后是孩子的孩子等等。
我发现一些解决方案至少满足了我的两个要求,但没有一个满足这三个要求。
解决方案: jsfiddle
var x = [
{id: 10, parent: 0, children: []},
{id: 20, parent: 10, children: []},
{id: 30, parent: 10, children: []},
{id: 40, parent: 30, children: []},
{id: 50, parent: 30, children: []},
{id: 60, parent: 30, children: []},
{id: 70, parent: 20, children: []},
{id: 80, parent: 20, children: []},
{id: 90, parent: 40, children: []},
{id: 100, parent: 40, children: []},
{id: 95, parent: 40, children: []},
{id: 110, parent: 50, children: []},
{id: 120, parent: 60, children: []},
{id: 130, parent: 0, children: []},
{id: 140, parent: 130, children: []},
{id: 150, parent: 140, children: []},
{id: 160, parent: 140, children: []},
{id: 170, parent: 140, children: []},
{id: 180, parent: 160, children: []},
{id: 190, parent: 160, children: []},
{id: 200, parent: 190, children: []}
];
进入这个:
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<ul>
<li>10
<ul>
<li>20
<ul>
<li>70</li>
<li>80</li>
</ul>
</li>
<li>30
<ul>
<li>40
<ul>
<li>90</li>
<li>95</li>
<li>100</li>
</ul>
</li>
<li>50
<ul>
<li>110</li>
</ul>
</li>
<li>60
<ul>
<li>120</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
<li>130
<ul>
<li>140
<ul>
<li>150</li>
<li>160
<ul>
<li>180</li>
<li>190
<ul>
<li>200</li>
</ul>
</li>
</ul>
</li>
<li>170</li>
</ul>
</li>
</ul>
</li>
</ul>
</body>
</html>
答案 0 :(得分:0)
您可以先构建树对象,然后渲染所需的html结构。
为了获得排序结果,我建议先使用两级方法对数据进行排序,先排序parent
,然后排序id
。
要返回所需级别,您可以将level
变量添加到getTree
,如果没有设置则初始化为零。
每个更深层次的增量值。
function getTree(array, level) {
var ul = document.createElement('ul');
level = level || 0;
array.forEach(function (a) {
var li = document.createElement('li');
li.appendChild(document.createTextNode(a.id + ' level: ' + level));
Array.isArray(a.children) && li.appendChild(getTree(a.children, level + 1));
ul.appendChild(li);
});
return ul;
}
var data = [{ id: 10, parent: 0 }, { id: 20, parent: 10 }, { id: 30, parent: 10 }, { id: 40, parent: 30 }, { id: 50, parent: 30 }, { id: 60, parent: 30 }, { id: 70, parent: 20 }, { id: 80, parent: 20 }, { id: 90, parent: 40 }, { id: 100, parent: 40 }, { id: 95, parent: 40 }, { id: 110, parent: 50 }, { id: 120, parent: 60 }, { id: 130, parent: 0 }, { id: 140, parent: 130 }, { id: 150, parent: 140 }, { id: 160, parent: 140 }, { id: 170, parent: 140 }, { id: 180, parent: 160 }, { id: 190, parent: 160 }, { id: 200, parent: 190 }],
tree = function (data, root) {
var r = [],
o = {};
data.forEach(function (a) {
a.children = o[a.id] && o[a.id].children;
o[a.id] = a;
if (a.parent === root) {
r.push(a);
} else {
o[a.parent] = o[a.parent] || {};
o[a.parent].children = o[a.parent].children || [];
o[a.parent].children.push(a);
}
});
return r;
}(data.sort(function (a, b) { return a.parent - b.parent || a.id- b.id; }), 0);
document.body.appendChild(getTree(tree));
console.log(tree);
&#13;
答案 1 :(得分:-1)
如果我的小提琴消失了,这是我的完整解决方案:
<html>
<script>
window.onload = function () {
// STEP 1: Get a flat array of objects.
/* A flat (1 dimensional) array, which can later be turned into a tree, since each array item has an id and parent property. */
var x = [
{id: 10, parent: 0, children: []}, // 2 immediate children, root node
{id: 20, parent: 10, children: []}, // 2 immediate children
{id: 30, parent: 10, children: []}, // 3 immediate children
{id: 40, parent: 30, children: []}, // 3 immediate children
{id: 50, parent: 30, children: []}, // 1 immediate children
{id: 60, parent: 30, children: []}, // 1 immediate children
{id: 70, parent: 20, children: []}, // 0 immediate children
{id: 80, parent: 20, children: []}, // 0 immediate children
{id: 90, parent: 40, children: []}, // 0 immediate children
{id: 100, parent: 40, children: []}, // 0 immediate children
{id: 95, parent: 40, children: []}, // 0 immediate children
{id: 110, parent: 50, children: []}, // 0 immediate children
{id: 120, parent: 60, children: []}, // 0 immediate children
{id: 130, parent: 0, children: []}, // 1 immediate children, root node
{id: 140, parent: 130, children: []}, // 3 immediate children
{id: 150, parent: 140, children: []}, // 0 immediate children
{id: 160, parent: 140, children: []}, // 2 immediate children
{id: 170, parent: 140, children: []}, // 0 immediate children
{id: 180, parent: 160, children: []}, // 0 immediate children
{id: 190, parent: 160, children: []}, // 1 immediate children
{id: 200, parent: 190, children: []} // 0 immediate children; 5 levels deep (level = 4, since start level is 0)
];
// STEP 2: Turn the flat array into a tree (hierarchical) array.
function tierData (arr) {
/*
Params:
@arr = flat array. Each array item is an object containing id, parent, and children properties.
Description:
Takes a flat array and turns into into a tree (hierarchical) array.
*/
for (var i = 0; i < arr.length; i++) {
arr.forEach(function (n) {
if (n.parent === arr[i].id) {
arr[i].children.push(n);
}
});
}
return arr.filter(function (n) { return n.parent === 0 }); // Only return root nodes and their children, children's children, etc.
}
var td = tierData(x);
//console.log(td);
// STEP 3: Assign a "level" property to each tree level. Numeric sort tree items for each level in the tree.
function treeSortAndLevel (treeArr,flatArr,flatIndex) {
/*
Params:
@treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn.
@flatArr = A flat array on which @treeArr is based.
@flatIndex = DON'T PASS AN ARG. This is assigned a value by subsequent recursive fn calls.
Description:
Returns a tree which is numeric sorted at each level and each tree node is assigned a level property value, starting with root node(s) level = 0.
*/
// If not provided (ie the fn's first call), create an indexer for the flat array.
if (flatIndex === undefined) {
var flatIndex = {};
for (var i = 0; i < flatArr.length; i++) {
flatIndex[flatArr[i].id] = flatArr[i];
}
}
for (var i = 0; i < treeArr.length; i++) {
// Numeric sort the current treeArr tier (ie array) by id.
treeArr.sort(function (a, b) { return a.id - b.id; });
// Determine and set the treeArr item's level.
var parentId = treeArr[i].parent;
var level = 0;
while (parentId !== 0) {
level++;
var ancestor;
ancestor = flatIndex[parentId];
parentId = ancestor.parent;
}
treeArr[i].level = level;
treeSortAndLevel(treeArr[i].children,flatArr,flatIndex);
}
return treeArr;
}
var sortedAndLeveldTree = treeSortAndLevel(td,x);
console.log(sortedAndLeveldTree);
// STEP 4: Append a multi-tiered unordered list to the DOM for the sorted and level numbered tree.
function printTree (treeArr) {
/*
Params:
@treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn.
Description:
Prints a tree to the console.
*/
for (var i = 0; i < treeArr.length; i++) {
var indent = '';
var level = treeArr[i].level;
while (level > 0) {
indent += ' -- ';
level--;
}
console.log(indent + treeArr[i].id);
printTree(treeArr[i].children);
}
}
function createTreeDOM (treeArr, ul) {
/*
Params:
@treeArr = A tree (hierarchical) array, created from a flat array using the tierData fn.
@ul = DON'T PASS AN ARG. This is assigned a value by subsequent recursive fn calls.
Description:
Returns an unordered list tree (DOM element).
*/
if (ul === undefined) {
ul = document.createElement('ul');
}
for (var i = 0; i < treeArr.length; i++) {
var li = document.createElement('li');
var tx = document.createTextNode(treeArr[i].id);
li.appendChild(tx);
if (treeArr[i].children.length > 0) {
var subUL = document.createElement('ul');
li.appendChild(subUL);
createTreeDOM(treeArr[i].children, subUL);
}
ul.appendChild(li);
}
return ul;
}
// Alternatively, print the sorted and level numbered tree to the console in a tree-like style using the printTree fn:
//printTree(sortedAndLeveldTree);
var p = document.createElement('p');
p.innerHTML = 'The below tree was dynamically created from a flat array of objects using JS. Tree items (the objects, not the DOM elements) are assigned a level property, starting with 0 for root items. Tree items are sorted by their id at each tier (tree level).';
document.body.appendChild(p);
var treeDOM = createTreeDOM(sortedAndLeveldTree);
document.body.appendChild(treeDOM);
}
</script>
</html>