【问题标题】:How does this JavaScript numeric compare function actually work? [duplicate]这个 JavaScript 数字比较函数实际上是如何工作的? [复制]
【发布时间】:2015-09-17 16:55:02
【问题描述】:

我知道要对整数进行排序,我需要像这样将比较函数传递给 sort():

function(a, b){return a-b}

但我想知道的是它实际上是如何工作的。意思是,如果 a-b 的结果为负,那么 b 排在 a 之前,如果 a-b 为正,那么 a 排在 b 之前?是对的吗?如果 a-b = 0 会发生什么?

【问题讨论】:

标签: javascript function sorting integer compare


【解决方案1】:

这是对 API 进行排序的常见模式。如果返回值为 0,则表示项目(为了排序)相等。

在实践中,具有相等键的排序函数的行为具有一定的重要性。当键相等时,按照它们所在的顺序(相对于彼此)离开条目的排序称为 stable 排序。在 JavaScript 中,.sort() API 被明确指定为不一定是稳定的。这意味着排序函数可能给你留下一个数组,其中两个比较相等的元素在排序完成时被交换。

该行为会影响您使用.sort() 函数的方式。假设您有一个对象列表:

var list = [{
  firstName: "Louis",
  lastName: "Adams",
  // ...
}, {
  // ...
}];

因此,具有名字字段和姓氏字段的对象。如果 JavaScript .sort() API 需要稳定,那么您可以按照人们期望的方式对列表进行排序:

function ocompare(key, o1, o2) {
  return o1[key] < o2[key] ? -1 :
         o1[key] > o2[key] ? 1 :
         0;
}
list.sort(function(o1, o2) {
  return ocompare("firstName", o1, o2);
});
list.sort(function(o1, o2) {
  return ocompare("lastName", o1, o2);
});

也就是说,您可以先按名字排序,然后按姓氏排序,然后您会得到一个按姓氏排序的列表,并且您可以确定“Adams, John”会出现在列在“亚当斯,扎克”之前。 (请注意,我们排序的 firstless 重要的键。)

但是,JavaScript .sort() API 不一定稳定,因此您不能依赖它。相反,您必须通过.sort() 一次性完成所有您想要的排序比较:

function ocompare(o1, o2) {
  var keys = [];
  for (var i = 2; i < arguments.length; keys[i] = arguments[i], ++i);

  for (i = 0; i < keys.length; ++i) {
    if (o1[keys[i]] < o2[keys[i]])
      return -1;
    if (o1[keys[i]] > o2[keys[i]])
      return 1;
  }
  return 0;
}
list.sort(function(o1, o2) {
  return ocompare(o1, o2, "lastName", "firstName");
});

请注意,这(虽然涉及更多一点)可能比执行依赖于稳定排序的两遍方法更快,因为当姓氏字段不同时不需要进行比较。

【讨论】:

  • 我习惯于从arguments 对象中复制内容;这在这里不是很必要,但我认为它使它更整洁。在 ES2015 中,可以使用 ... 表示法。
【解决方案2】:

意思是,如果a-b的结果为负,那么b排在a之前,如果a-b为正,那么a排在b之前?对吗?

反之亦然。如果返回值为负数,则a放在b之前。

如果 a-b = 0 会发生什么?

这意味着值相等,它们的相对顺序无关紧要。

来自MDN documentation

如果提供了compareFunction,则数组元素根据比较函数的返回值进行排序。如果ab 是被比较的两个元素,那么:

  • 如果compareFunction(a, b)小于0,则将a排序到比b低的索引,即a在前。

  • 如果 compareFunction(a, b) 返回 0,则 a 和 b 彼此保持不变,但对所有不同元素进行排序。注意:ECMAscript 标准不保证这种行为,因此并非所有浏览器(例如至少可以追溯到 2003 年的 Mozilla 版本)都尊重这一点。

  • 如果 compareFunction(a, b) 大于 0,则将 b 排序到比 a 低的索引。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-11-03
    • 2014-10-24
    • 2014-06-14
    • 1970-01-01
    • 2015-04-29
    相关资源
    最近更新 更多