在Javascript(Node.js)中使用分层组对多维对象进行排序

时间:2013-02-06 17:46:09

标签: javascript node.js sorting reference pass-by-reference

我有一个分层对象,我通过走过父母对孩子进行分类来对孩子进行分类。这有效。但现在,我需要选择性地打破层次结构并创建新的虚拟约束。

为了说明这一点,让我们举一个拥有 x Wifes的男人的例子。每个妻子都有 y 孩子。我可以按照妻子或每个男人的妻子来分类孩子。

Man01   Wife01a     Kid01aA
                    Kid01aB
        Wife01b     Kid01bC
                    Kid01bD
Man02   Wife02c     Kid02cE
                    Kid02cF
        Wife02d     Kid02dG
                    Kid02dH

让我们给他们起名字:

Murphy  Winnie  Kurt
                Kara
        Wendy   Klaus
                Klea
Marley  Wonda   Kasper
                Kyra
        Wilma   Kevin
                Karla

考虑在父母的字母顺序中对它们进行排序:

Marley  Wilma   Karla
                Kevin
        Wonda   Kasper
                Kyra
Murphy  Wendy   Klaus
                Klea
        Winnie  Kara
                Kurt

但是现在,我们希望能够对属于一个男人的孩子,或一般的妻子,或一般的孩子进行排序?

Marley  Wilma   Karla
        Wonda   Kasper
        Wilma   Kevin
        Wonda   Kyra
Murphy  Winnie  Kara
        Wendy   Klaus
        Wendy   Klea
        Winnie  Kurt

这是一个简单的简化虚构对象。实际上,我不是按字母顺序排序,而是对许多属性进行多列排序。

将结果输出到表格很好,但处理本身已经花费了大量的时间和内存。我不想让这进一步复杂化。

如果这没有问题,我只是将对象展平为数组中的表,将每个多列排序链接成超级多列排序,并从最近的完整循环的最近共同祖先开始重新组合

但我试图以更有效的方式解决这个问题,而不将对象转换为完整的表格数组。

  • 我如何解决这个问题? 实际上两次循环遍历每一个?
    • 也许有一种'众所周知'的解决方案,这种排序我还不知道呢?
    • 也许有一些魔法可以使用所有“虚拟”父母的引用创建类似于表的记录,然后将这些引用分组回层次结构而不循环遍历它们?

以下是我所指的Object类型的示例: Object,我的意思是{},尽管该对象包含多个成员的对象[]的数组{}

{
    "men"   : [
        {
            "name"  : "Murphy",
            // a lot of properties
            "wifes" : [
                {
                    "name"  : "Winnie",
                    // a lot of properties
                    "kids"  : [
                        {
                            "name"  : "Kurt",
                            // a lot of properties
                        }, {}, {} // etc...
                    ]
                }, {}, {} // etc...
            ]
        }, {}, {} // etc...
    ]
}

请注意,在这种情况下,我的例子是错误的,因为男人,妻子和孩子都是人类。但实际上有不同的对象具有不同的属性。假设有多个宇宙,我应该选择宇宙,行星,土壤或其他东西。 ;)

1 个答案:

答案 0 :(得分:0)

  

我们希望能够对属于男性的孩子进行排序

然后我会像这样安排他们:

Marley  Karla   Wilma   
        Kasper  Wonda
        Kevin   Wilma
        Kyra    Wonda
Murphy  Kara    Winnie
        Klaus   Wendy
        Klea    Wendy
        Kurt    Winnie

当然,由于每个孩子只有一个母亲没有太大区别,但对于您的实际数据,这可能会有所不同。

然而,您现在已经可以看到,您只需要为每个人排序每个kids数组。

因此,通常情况下,您应该首先进行分组并对组进行排序,而不是扁平化为大型表数组,多列排序,并按照您的建议重新组合结果 - 有点像{{3 }}

var men = data["men"];
men.forEach(function (man) {
    var kids = {};
    var wifes = man["wifes"];
    for (var i=0; i<wifes.length; i++) {
        var wkids = wifes[i]["kids"];
        for (j=0; j<wkids.length; j++) {
            var id = wkids[j]["name"];
            if (id in kids) {
                kids[id].mothers.push(wifes[i]);
            else {
                kids[id] = wkids[i];
                kids[id].mothers = [ wifes[i] ];
            }
        }
    }
    // if the id is the sort criteria:
    man["kids"] = Object.keys(kids).sort().map(function(id) {
        return kids[id];
    });
    // else build the array first and then sort it:
    // man["kids"] = Object.values(kids).sort(function(kida, kidb) {
    //    <some kid comparison>
    // });

    // you might integrate this loop in the above, but it's independent:
    man["kids"].forEach(function(kid) {
        kid["mothers"].sort( /* some mother comparison */ );
    })
});
// now every man has a sorted "kids" array with each kid having a sorted "mothers" array