Javascript 按父项和类型对项目进行排序

Javascript 按父项和类型对项目进行排序,javascript,sorting,Javascript,Sorting,这可能是一个典型的任务,但我还没有在Wiki或这里找到一个优雅的解决方案 我有一个包含以下字段的元素列表:类型“c”或“e”-容器或元素、id、父级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]

这可能是一个典型的任务,但我还没有在Wiki或这里找到一个优雅的解决方案

我有一个包含以下字段的元素列表:类型“c”或“e”-容器或元素、id、父级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,它不是很漂亮,但只使用了2次迭代,一次用于计数,一次用于更新。顺便说一句,如果有人会使用它:不按ID排序,您应该在需要时添加此功能

另外,有3行jquery.append来说明结果,仅此而已


p.p.S.除了承诺之外,有没有一种方法可以只在第一个任务完成后才给第二个任务打电话?我在最后一个列表的元素上调用了它,但不确定它是否正确。

在100多个元素上循环不会花费太多时间来冻结页面

可以使用循环

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.

希望对您有所帮助……

您可以使用对象作为关联数组一次完成这项工作:

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层的树,也存在通用解决方案。它使用类似的方法,并没有比这复杂多少。

我自己的答案正在更新中。不太好,但效果很好。

唯一的坏主意是:1将容器和没有父元素的元素带到另一个数组中2对它们进行排序:位于前3位的容器遍历其他元素,并给出它们的位置,如父元素+0.001,例如4个固定浮点数子元素的顺序重要吗?还有,你是如何创建这个列表的?不是很好。如果您有一个没有子排序的想法-请写下来。如果树有两个以上的级别,这个方法将如何工作?这个方法将不适用于两个以上的级别。。。这个问题提到只有两个级别。然而,如果我们需要更多,我们需要使用递归。在我的例子中,只有两个级别。但我在考虑迭代次数。至少,正如我所看到的,1+容器数量+容器数量。@philosophocat阅读它只有2级以上,然后是100个元素-请更仔细地使用标点符号:@philosophocat你得到解决方案了吗?或者我们需要修改这个吗?非常感谢,您的排序很有趣,我很乐意稍后使用它,但这次我想在元素的属性中添加位置号。@philosophocat排序的问题是,构建任何使用标识、嵌入html列表实现的树的常规表示,树控件或etc已经要求对树项进行偏序:每个节点的所有子节点都必须继承该节点,并继承其任何兄弟节点或更高的节点。换句话说,必须对项目进行排序,以便在不重新排序项目的情况下折叠/展开树。存在不止一种这样的排序。换句话说,树只能按级别排序。@philosophocat所以,如果使用position属性,则有三种情况。1位置属性值已经符合树结构-无需进一步处理,只需按位置顺序显示项目,缩进元素。2位置属性是任意的,您喜欢根据其项目的最小位置对类别进行排序,而不总是类别本身的位置-根据位置属性对项目进行预排序,然后运行树形成函数。3位置属性是任意的,你喜欢在自己的位置上对类别进行排序-运行树形函数,而不是像标题上那样在位置上进行水平排序。我不同意你的观点。关键是我不需要树——它破坏了应用程序的功能性。1,5年前,我写了一个评论树模块,但现在一切都变了:我不需要树,我用js而不是php。@philosophocat好的,我也没有争论。如果您不需要保持树状结构,我敢打赌这里没有人回答您,甚至没有人理解您的特定任务,特别是到目前为止,它意味着什么排序。制作一棵不是真正的树并不是一项普通的任务:但我很高兴你们自己找到了可行的解决方案。