JavaScript按多个(数字)字段对数组进行排序

47

我该如何实现一个

 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

3
你为什么要把数组语法放在(破损的)字符串字面量语法内部? - I Hate Lazy
我正在使用这种方式的JSON,有更好的方法吗? - coiso
1
由于您将数组分配给“items”变量,因此您已经处于JavaScript环境中,因此先将其表示为JSON标记,然后解析它并没有太多意义。如果这是表示从服务器发送的JSON标记,则更好的表示方法是摆脱额外的“var items = ...;”语法,并仅显示它作为标记,并附有一条说明它是您的服务器端标记。 - I Hate Lazy
可能是[按两个值排序,优先考虑其中一个值]的重复问题(https://dev59.com/cm455IYBdhLWcg3wCPjh)。 - Boris Yakubchik
3个回答

115

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

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);


使用运算符“-”可能会导致问题,因为值可能是字符串。 - xhg
这正是我所说的。- 仅适用于数字。我并不是说你错了。正如我在答案中所说,我提供了一个通用解决方案。 - xhg
1
'12' 应该小于 '3'。 - xhg
4
记住,显式比隐式更好。如果您想将值作为字符串按 任何情况 进行比较,请使用 String.localeCompare()< 是有歧义的;它的结果取决于操作数的类型 - 以及类型转换,如果它们不同的话。 - raina77ow
“<”仍然是错误的操作符,因为您只想对第一个比较相等的数字运行第二个比较。 “-”操作符可以捕获所有三种比较情况(> 0、0、<0)。 - Dogoku
显示剩余3条评论

9
您可以通过创建通用函数来避免硬编码。
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实现进行比较。 - raina77ow

0

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);


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