【问题标题】:JavaScript sort array by multiple (number) fieldsJavaScript 按多个(数字)字段对数组进行排序
【发布时间】:2012-10-24 02:02:04
【问题描述】:

我怎样才能实现一个

 ORDER BY sort1 DESC, sort2 DESC

JSON 数组中的逻辑如下:

    var items = '[
          {
            "sort1": 1,
            "sort2": 3,
            "name" : "a",
          },
          {
            "sort1": 1,
            "sort2": 2,
            "name" : "b",
          },
          {
            "sort1": 2,
            "sort2": 1,
            "name" : "c",
          }
    ]';

导致新订单:

b,a,c

【问题讨论】:

  • 你为什么把你的数组语法放在(损坏的)字符串文字语法中?
  • 我是这样使用JSON的,有没有更好的办法?
  • 由于您将 Array 分配给 items 变量,因此您已经处于 JavaScript 环境中,因此首先将其表示为 JSON 标记然后解析没有太大意义它。如果这是为了表示从服务器发送的 JSON 标记,那么更好的表示方法是去掉额外的 var items = ...; 语法,并将其显示为标记,并附上说明这是您的服务器端标记的注释。

标签: javascript json sorting


【解决方案1】:

您应该相应地设计您的排序功能:

items.sort(function(a, b) {
  return a.sort1 - b.sort1  ||  a.sort2 - b.sort2;
});

(因为||运算符的优先级低于-一个,所以这里不用括号)。

逻辑很简单:如果 a.sort1 - b.sort1 表达式的计算结果为 0(因此这些属性相等),它将继续计算 || 表达式 - 并返回 a.sort2 - b.sort2 的结果。

作为旁注,您的 items 实际上是一个字符串文字,您必须 JSON.parse 才能获得一个数组:

const itemsStr = `[{
    "sort1": 1,
    "sort2": 3,
    "name": "a"
  },
  {
    "sort1": 1,
    "sort2": 2,
    "name": "b"
  },
  {
    "sort1": 2,
    "sort2": 1,
    "name": "c"
  }
]`;
const items = JSON.parse(itemsStr);
items.sort((a, b) => a.sort1 - b.sort1 || a.sort2 - b.sort2);
console.log(items);

【讨论】:

  • 使用运算符- 可能会导致问题,因为该值可能是字符串。
  • 恐怕您在评论和回答中都错过了这一点。使用 - 而不是 < 是强制将操作数作为数字而不是字符串进行比较的方法。请记住,'12' < '3' 在 JavaScript 中的计算结果为 true
  • 这正是我要说的。 - 仅适用于数字。我不是说你错了。正如我在回答中所说,我正在提供一个通用的解决方案。
  • - only applies to numbers - 不,不是。 '12' - '3' 的计算结果为 9 (> 0),将前一个操作数放在更高的位置。 '12' true,颠倒顺序。
  • 记住,显式优于隐式。如果您希望在任何情况中将值作为字符串进行比较,请改用String.localeCompare()< 不明确;其结果取决于操作数类型 - 和类型杂耍,如果它们不同的话。
【解决方案2】:

您可以通过创建通用函数来避免硬编码

function sortByMultipleKey(keys) {
    return function(a, b) {
        if (keys.length == 0) return 0; // force to equal if keys run out
        key = keys[0]; // take out the first key
        if (a[key] < b[key]) return -1; // will be 1 if DESC
        else if (a[key] > b[key]) return 1; // will be -1 if DESC
        else return sortByMultipleKey(keys.slice(1))(a, b);
    }
}

跑步

items.sort(sortByMultipleKey(['sort1', 'sort2']));

会有你的

[ { sort1: 1, sort2: 2, name: 'b' },
  { sort1: 1, sort2: 3, name: 'a' },
  { sort1: 2, sort2: 1, name: 'c' } ]

【讨论】:

  • 很抱歉,这种泛型函数的实现效率太低了。不仅在这里使用递归是可疑的(您可以迭代键列表直到比较结果非零),对于每个“比较未命中”,都会生成一个新的比较函数实例。例如,将您的代码与lodash implementation 进行比较。
【解决方案3】:

const itemsStr = `[{
    "sort1": 1,
    "sort2": 3,
    "name": "a"
  },
  {
    "sort1": 1,
    "sort2": 2,
    "name": "b"
  },
  {
    "sort1": 2,
    "sort2": 1,
    "name": "c"
  }
]`;
const items = JSON.parse(itemsStr);
items.sort((a, b) => a.sort1 - b.sort1 || a.sort2 - b.sort2);
console.log(items);

【讨论】:

    猜你喜欢
    • 2011-09-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-04
    相关资源
    最近更新 更多