【问题标题】:Sorting an array of objects in a specific order按特定顺序对对象数组进行排序
【发布时间】:2015-04-13 09:15:45
【问题描述】:

我有以下数组:

        [{"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_modelo”升序按“cod_nivel”分组来排序这个对象数组。所以结果应该是:

    [{"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 分组)排序。

我希望我已经清楚地解释了自己,有人可以帮助我。

【问题讨论】:

标签: javascript arrays json sorting


【解决方案1】:

您可以像这样在关联数组中分配索引

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' } ]

【讨论】:

  • 但这不是专门按照我需要的顺序订购 cod_modelos 的,不是吗? 1.INC1 2.INC2 3.PRIM1 4.PRIM2 5.BAC1 6.BAC2
  • @Egidi 这正是重点。您不必对它进行两次排序(首先按cod_modelo,然后按cod_nivel)。它会给你预期的结果。我还解释了比较规则。请检查。
  • 我正在测试它,但它没有给出所需的结果。我可以理解我不需要对它进行两次排序,但正如所说,我需要先在数组中放入对象“cod_nivel”='INC1',然后是'INC2'对象,然后是'PRIM1'......使用您的代码在数组的开头排序“BAC1”对象,因为它按 cod_nivel 升序排序,而 BAC1 在 INC1 之前......我错了吗?
  • @Egidi 我在您的排序中没有看到模式。当你先根据cod_modelo再根据cod_nivel排序时,为什么在预期结果中D出现在B之后?
  • 是的,cod_modelo 必须按升序排序 (a,b,c,d,e,f,g...) 但 cod_nivel 必须以特定方式排序 ( 1. INC1 2. INC2 3. PRIM1 4. PRIM2 5. BAC1 6. BAC2)...注意不是升序...是固定顺序。也许我没有很好地解释自己...顺便说一句,我非常感谢您的帮助。
【解决方案2】:
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所说,前一个版本的计算效果不是很好。所以这里是数字/数字或字符串/字符串比较的类型安全版本。

【讨论】:

  • 可以解释一下你在做什么以及为什么。
  • 注意:这将在所有环境中工作,因为 JavaScript 的排序不能保证在所有环境中都是稳定的。它留给实现。
猜你喜欢
  • 1970-01-01
  • 2010-09-26
  • 1970-01-01
  • 1970-01-01
  • 2019-11-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-02-19
相关资源
最近更新 更多