按特定顺序对对象数组进行排序

3

我有以下数组:

        [{"cod_nivel":"INC2","cod_modelo":"D"},   
        {"cod_nivel":"PRIM1","cod_modelo":"B"},   
        {"cod_nivel":"INC2","cod_modelo":"B"},  
        {"cod_nivel":"INC1","cod_modelo":"D"},
        {"cod_nivel":"PRIM1","cod_modelo":"D"},
        {"cod_nivel":"BAC2","cod_modelo":"B"},    
        {"cod_nivel":"BAC2","cod_modelo":"D"},    
        {"cod_nivel":"BAC2","cod_modelo":"A"}]

我需要按照 "cod_nivel" 分组并按照 "cod_modelo" 升序排序这个对象数组。因此结果应该是:
    [{"cod_nivel":"INC1","cod_modelo":"D"},    
    {"cod_nivel":"INC2","cod_modelo":"B"},
    {"cod_nivel":"INC2","cod_modelo":"D"},    
    {"cod_nivel":"PRIM1","cod_modelo":"B"},    
    {"cod_nivel":"PRIM1","cod_modelo":"D"},
    {"cod_nivel":"BAC2","cod_modelo":"A"},    
    {"cod_nivel":"BAC2","cod_modelo":"B"},    
    {"cod_nivel":"BAC2","cod_modelo":"D"}]

好的,我制作了这段代码,首先按cod_nivel排序数组,然后按cod_modelo排序:

var sortedArray = array.sort(function (a, b) {
    return (a["cod_nivel"] > b["cod_nivel"]) ? 1 : -1;
}).sort(function (a, b) {
    if (a["cod_nivel"] == b["cod_nivel"])
        return (a["cod_modelo"] > b["cod_modelo"]) ? 1 : -1;
    else
        return 0;
});

问题在于此代码还按“cod_nivel”排序,因此获得的数组将是:
    [{"cod_nivel":"BAC2","cod_modelo":"A"},    
    {"cod_nivel":"BAC2","cod_modelo":"B"},    
    {"cod_nivel":"BAC2","cod_modelo":"D"},
    {"cod_nivel":"INC1","cod_modelo":"D"},    
    {"cod_nivel":"INC2","cod_modelo":"B"},
    {"cod_nivel":"INC2","cod_modelo":"D"},    
    {"cod_nivel":"PRIM1","cod_modelo":"B"},    
    {"cod_nivel":"PRIM1","cod_modelo":"D"}]

请注意,BAC2 cod_nivel 对象在开头。
我的需求是按照给定的顺序首先按cod_nivel排序,顺序如下:
1. INC1 2. INC2 3. PRIM1 4. PRIM2 5. BAC1 6. BAC2
我假设我需要一个具有“cod_nivel”固定顺序的数组,并且在排序时使用它,但是我不知道如何使用它,因此我没有将其包含在我的方法中。
var order_arr = ['INC1', 'INC2', 'PRIM1', 'PRIM2', 'BAC1', 'BAC2']

接下来,按照cod_modelo的顺序排序(每个cod_nivel分组)。希望我已经表达清楚,有人可以帮助我。

将您的排序代码放在一个回调函数中:首先比较“code_nivel”属性,如果相同,则按“cod_modelo”排序。 - Sirko
你试过 http://underscorejs.org/ 吗?使用 Underscore.js 做这样的事情非常容易。 - Alaa-GI
可能是按特定顺序对对象数组进行排序的重复问题。 - Gajus
2个回答

10

您可以在关联数组中分配索引,例如:

var cod_nivel_order = {
    'INC1': 0,
    'INC2': 1,
    'PRIM1': 2,
    'PRIM2': 3,
    'BAC1': 4,
    'BAC2': 5
};

然后你可以像这样排序

function compare(a, b) {
    if (a === b) {
        return 0;
    }
    return a < b ? -1 : 1;
}

var sortedArray = array.sort(function (a, b) {

    // First compare corresponding values of `cod_nivel` from `cod_nivel_order`
    var index_result = compare(cod_nivel_order[a.cod_nivel],
        cod_nivel_order[b.cod_nivel]);

    // If they are equal
    if (index_result === 0) {

        // Return the result of comparing `cod_modelo`s
        return compare(a.cod_modelo, b.cod_modelo);
    }

    return index_result;
});

现在的结果将会是

[ { cod_nivel: 'INC1', cod_modelo: 'D' },
  { cod_nivel: 'INC2', cod_modelo: 'B' },
  { cod_nivel: 'INC2', cod_modelo: 'D' },
  { cod_nivel: 'PRIM1', cod_modelo: 'B' },
  { cod_nivel: 'PRIM1', cod_modelo: 'D' },
  { cod_nivel: 'BAC2', cod_modelo: 'A' },
  { cod_nivel: 'BAC2', cod_modelo: 'B' },
  { cod_nivel: 'BAC2', cod_modelo: 'D' } ]

1
@Egidi 这正是关键所在。您不必两次排序(首先按cod_modelo,然后按cod_nivel)。它将给您预期的结果。我也解释了比较规则。请检查。 - thefourtheye
我认为我需要一个按照“cod_nivel”固定顺序的数组,并在排序时使用它,但我不知道如何使用它,所以我没有在我的方法中包含它。 - Egidi
@Egidi 啊,我明白了。给我一点时间,我会修复它的。 - thefourtheye
好的,我修改了我的解释,希望现在更清晰了。 - Egidi
@Egidi 好的,我已经修复了。请检查。 - thefourtheye
显示剩余6条评论

3
var data = [{
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "PRIM1",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "INC1",
    "cod_modelo": "D"
}, {
    "cod_nivel": "INC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "PRIM2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "B"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "D"
}, {
    "cod_nivel": "BAC2",
    "cod_modelo": "A"
}];
var sortOrder = ['INC1', 'INC2', 'PRIM1', 'PRIM2', 'BAC1', 'BAC2'];
data.sort(function (a, b) {
    // first have a look at cod_nivel
    // get the indices of the given sortOrder
    // take the difference of the indices
    var delta = sortOrder.indexOf(a.cod_nivel) - sortOrder.indexOf(b.cod_nivel);
    // test, if the indices are the same
    if (delta === 0) {
        // the comparison should usually return 0,
        // but this will here not work. we need
        // the comparison of the second sort order of cod_modelo.
        // take the variables and make a real comparison,
        // while we expecting strings to be compared
        return a.cod_modelo === b.cod_modelo ? 0 : (a.cod_modelo < b.cod_modelo ? -1 : 1);
    }
    // otherwise return the delta
    return delta;
});

正如thefortheye所提到的,以前的版本在计算方面表现不佳。因此,这里是针对数字/数字或字符串/字符串比较的类型安全版本。


可以解释一下你在做什么以及为什么要这样做吗? - Liam
注意:由于JavaScript的排序在所有环境中并不保证稳定性,因此这种方法并不能在所有环境中都奏效。具体实现需要自行决定。 - thefourtheye

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接