【问题标题】:Sort an array of objects by multiple properties按多个属性对对象数组进行排序
【发布时间】:2013-07-30 09:27:09
【问题描述】:

我有一个这样的对象数组:

var a = [
    { id: 1, score: 1, isCut: false, dnf: false },
    { id: 2, score: 2, isCut: false, dnf: false },
    { id: 3, score: 3, isCut: false, dnf: false },
    { id: 4, score: 4, isCut: false, dnf: false },
    { id: 5, score: 5, isCut: true, dnf: true },
    { id: 6, score: 6, isCut: true, dnf: false },
    { id: 7, score: 7, isCut: true, dnf: false },
    { id: 8, score: 8, isCut: true, dnf: false },
    { id: 9, score: 9, isCut: true, dnf: false },
    { id: 10, score: 0, isCut: false, dnf: false },
    { id: 11, score: -1, isCut: false, dnf: false },
    { id: 12, score: -2, isCut: false, dnf: true },
    { id: 13, score: -3, isCut: false, dnf: false },
    { id: 14, score: -4, isCut: false, dnf: false },
    { id: 15, score: -5, isCut: false, dnf: false },
    { id: 16, score: 10, isCut: true, dnf: false }
];

我需要按以下标准对数组进行分组和排序:

  1. 如果dnf 为真,则对象移至底部;所有dnf-objects 都应该按分数排序
  2. 如果isCut 为真,则对象到底部,但在dnfs 上方;所有isCut-objects 都应该按分数排序
  3. rest 应按score 排序,如果分数相等,则按id

【问题讨论】:

标签: javascript arrays sorting


【解决方案1】:

(已更新)这是您在评论中提到的问题的答案。

a.sort(function(a, b) {
  if (a.dnf != b.dnf) {
    return a.dnf ? 1 : -1;
  }
  if (!(a.dnf && b.dnf) && a.isCut != b.isCut) {
    return a.isCut ? 1 : -1;
  }
  if (a.score != b.score) {
    return b.score - a.score; // descending
  }
  return b.id - a.id; // descending
});

结果:

[
  {"id":4,"score":4,"isCut":false,"dnf":false},   // the rest: order by score, id
  {"id":3,"score":3,"isCut":false,"dnf":false},   //
  {"id":2,"score":2,"isCut":false,"dnf":false},   //
  {"id":1,"score":1,"isCut":false,"dnf":false},   //
  {"id":10,"score":0,"isCut":false,"dnf":false},  //
  {"id":11,"score":-1,"isCut":false,"dnf":false}, //
  {"id":13,"score":-3,"isCut":false,"dnf":false}, //
  {"id":14,"score":-4,"isCut":false,"dnf":false}, //
  {"id":15,"score":-5,"isCut":false,"dnf":false}, //
  {"id":16,"score":10,"isCut":true,"dnf":false}, // isCut: order by score, id
  {"id":9,"score":9,"isCut":true,"dnf":false},   //
  {"id":8,"score":8,"isCut":true,"dnf":false},   //
  {"id":7,"score":7,"isCut":true,"dnf":false},   //
  {"id":6,"score":6,"isCut":true,"dnf":false},   //
  {"id":5,"score":5,"isCut":true,"dnf":true},   // dnf: order by score, id
  {"id":12,"score":-2,"isCut":false,"dnf":true} //
]

【讨论】:

  • 这是dnf首先订购的。 isCut 将无法准确订购。您首先需要isCut 为真的所有项目,然后是isCut 为假的项目。
  • @amberlamps 我听不懂。 OP 不想让dnf 对象降到最低点吗?那么我们应该先通过dnf 订购。
  • 您理解正确,但如果是true,他希望isCut 高于此值。所以它可以按照这个顺序看起来像true/truetrue/falsefalse/true
  • @amberlamps 知道了!感谢您的解释。
  • 你必须用很多不同的数据来测试它才能真正确定,但到目前为止我看起来真的很好。 +1
【解决方案2】:

使用数组中的比较器函数

您可以在这里查看答案:Sort array of objects by string property value in JavaScript

【讨论】:

    【解决方案3】:

    这是一种不同的方法,它使用数组进行排序,如果使用dnfisCut 属性而不同时查看两者,则这是不规则的。如果我们将两个值都带入真值表,那么排序顺序不会反映想要的顺序。

                       2*dnf+isCut
        dnf     isCut     value     order
    --------  --------  --------  --------
         0         0         0         0
         0         1         1         1
         1         1         3         2
         1         0         2         3
    

    为了更正排序顺序,我建议使用数组来获得正确的顺序。

    var data = [{ id: 1, score: 1, isCut: false, dnf: false }, { id: 2, score: 2, isCut: false, dnf: false }, { id: 3, score: 3, isCut: false, dnf: false }, { id: 4, score: 4, isCut: false, dnf: false }, { id: 5, score: 5, isCut: true, dnf: true }, { id: 6, score: 6, isCut: true, dnf: false }, { id: 7, score: 7, isCut: true, dnf: false }, { id: 8, score: 8, isCut: true, dnf: false }, { id: 9, score: 9, isCut: true, dnf: false }, { id: 10, score: 0, isCut: false, dnf: false }, { id: 11, score: -1, isCut: false, dnf: false }, { id: 12, score: -2, isCut: false, dnf: true }, { id: 13, score: -3, isCut: false, dnf: false }, { id: 14, score: -4, isCut: false, dnf: false }, { id: 15, score: -5, isCut: false, dnf: false }, { id: 16, score: 10, isCut: true, dnf: false }];
    
    data.sort(function (a, b) {
        function order(dnf, isCut) { return [0, 1, 3, 2][dnf * 2 + isCut]; }
    
        return order(a.dnf, a.isCut) - order(b.dnf, b.isCut) || b.score - a.score;
    });
    
    console.log(data);
    .as-console-wrapper { max-height: 100% !important; top: 0; }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-09-06
      • 2019-01-12
      • 1970-01-01
      • 2012-02-20
      • 2010-11-02
      相关资源
      最近更新 更多