这可能是一项典型的任务,但我还没有在Wiki或此处找到优雅的解决方案。
我有一个包含下一个字段的元素列表:类型('c'或'e' - 容器或元素), id , parent (0或id)。 我需要像这样对它们进行排序
• [1] container 1
— [2] child element
— [3] child element
• [4] container 2
— [5] child element
— [6] child element
• [7] element without parent (parent: 0)
• [8] element without parent
只有2个级别,但超过100个元素。如果采取一个事实,它在浏览器中计数, - 人们可以因为冻结页面而诅咒:(所以,我正在寻找漂亮的解决方案。
UPD 我写了solution,它不是很漂亮,但只使用了2次迭代(一次用于计数,一次用于更新。顺便说一下,如果有人会使用它:不按ID排序,如果需要,您应该添加此功能!)。
P.S。有3行jquery .append来说明结果,这就是全部。
P.P.S。有没有办法只有在第一次完成除了承诺之后才会调用第二次forEach?我在最后一个列表的元素上调用了它,但不确定它是否正确。
答案 0 :(得分:1)
“超过一百个元素”的循环不会花费太多时间来冻结页面......
可以使用循环
1) Take all Containers in an array. (say arrContainers)
2) Iterate over the containers one-by-one.
3) If the container does not have elements, then add them to another array (say arrEmptyContainers)
3) If the container has childs, add each container in an array (say arrFinalList) followed by its elements.
4) Append arrEmptyContainers under arrFinalList.
希望它有所帮助...
答案 1 :(得分:1)
您可以使用object作为关联数组一次完成这项工作:
var test_items = [
{ title:'child element 2.2', type:'e', id:6, parent:4 },
{ title:'child element 2.1', type:'e', id:5, parent:4 },
{ title:'container 1', type:'c', id:1, parent:0 },
{ title:'container 2', type:'c', id:4, parent:0 },
{ title:'child element 1.1', type:'e', id:2, parent:1 },
{ title:'child element 1.2', type:'e', id:3, parent:1 },
{ title:'element without parent A', type:'e', id:8, parent:0 },
{ title:'element without parent B', type:'e', id:7, parent:0 }
];
function itemsToTree2( items ) {
var tree2 = {};
for( var i=0; i<items.length; ++i ) {
var item = items[i];
if( item.type=='c' || item.parent==0 ) {
if( !tree2[item.id] ) {
var parent = { id:item.id, parent:0, children:[] };
tree2[item.id] = parent;
}
tree2[item.id].title = item.title;
tree2[item.id].type = 'c';
} else {
if( !tree2[item.parent] ) {
var parent = { id:item.parent, parent:0, children:[] };
tree2[item.parent] = parent;
}
tree2[item.parent].children.push(item);
}
}
return tree2;
}
var test_tree2 = itemsToTree2(test_items);
console.log(test_tree2);
不确定它是否会明显更快......如果您知道每个容器都会出现在输入数据中的元素之前 - 上面的代码可以简化:
function itemsToTree2( items ) {
var tree2 = {};
for( var i=0; i<items.length; ++i ) {
var item = items[i];
if( item.type=='c' || item.parent==0 ) {
item.children = [];
tree2[item.id] = item;
} else {
tree2[item.parent].children.push(item);
}
}
return tree2;
}
如果您需要按字母顺序对树进行排序(按标题)(通常是这种情况),则需要额外处理:
function sortTree2( tree2, comparator ) {
var tree2array = [];
for( var id in tree2 )
tree2array.push( tree2[id] );
tree2array.sort(comparator);
for( var i=0; i<tree2array.length; ++i )
tree2array[i].children.sort(comparator);
return tree2array;
}
var sorted_tree2 = sortTree2( test_tree2, function(a,b) {
return a.title > b.title;
});
console.log(sorted_tree2);
也存在超过2级的树木的一般解决方案。它使用类似的方法,并没有比这更复杂。
答案 2 :(得分:0)
我自己的答案是更新。不太好,但有效。