JavaScript的sort(compareFunction)函数是如何工作的?

7
var arr = [5, 2, 1, -10, 8];

arr.sort(function(a, b) {
  console.log(a,b)
  return b - a;

}) ; // 8, 5, 2, 1, -10

这个回调函数是如何工作的?

选择a和b的原则是什么?

请从内部解释这个特定的例子。

输出console.log(首先,请解释这个输出):

  5 2
  2 1
  1 -10
 -10 8
  1 8
  2 8
  5 8

如果返回正数则交换,否则不交换。? - Mahi
1
我很困惑,你到底想要什么? - Josh Lin
此外,关于Pablo所提供的进一步阅读:https://dev59.com/cWAf5IYBdhLWcg3w_G2r#24080786 - VLAZ
它按照文档描述的方式工作。 - user663031
请解释这个输出。引擎正在询问各种对的顺序。引擎在项目之间进行最优数量的比较,以允许它对输入进行排序。 - user663031
3个回答

20

这取决于具体的实现方式。这个实现看起来像是插入排序,针对这么多数据(可能会不同,例如Chrome,以及少于10个或多于10个数据时的不同实现),它会从索引0开始遍历,如果在最后两个数据上没有发生交换,那么就停止了,否则就向后回到索引0。

基本上,它按照这个顺序进行测试和更改

5   2   1 -10   8   original order
5   2
    2   1
        1 -10
          -10   8   swap
            8 -10
        1   8       swap
        8   1
    2   8           swap
    8   2
5   8               swap
8   5  2    1 -10   result

更复杂的排序展示了更清晰的过程,其中有两个大值需要移到数组的另一侧

8   9   1   2   3   4   original array
8   9
    9   1               swap
    1   9
8   1                   swap
1   8
        9   2           swap
        2   9
    8   2               swap
    2   8
1   2
            9   3       swap
            3   9
        8   3           swap
        3   8
    2   3
                9   4   swap
                4   9
            8   4       swap
            4   8
        3   4
1   2   3   4   8   9   result

仅为示例,不适用于所有用户代理程序(例如Edge不支持,但Chrome支持)

var array = [8, 9, 1, 2, 3, 4];
console.log(JSON.stringify(array));
array.sort(function (a, b) {
    console.log(a , b, JSON.stringify(array));
    return a - b;
});
console.log(JSON.stringify(array));
.as-console-wrapper { max-height: 100% !important; top: 0; }


@Feathercrown,我看到了“sort(compareFunction)是如何工作的?” - Nina Scholz
好的,他们最初的问题问为什么,无论标题如何,但他们无论如何都改变了它。 - Feathercrown
您的答案正确性取决于浏览器使用的排序算法和数据本身的性质,因此在一个浏览器中它可能是正确的,在另一个浏览器中采取的操作可能会有所不同。 - Justinas
@Justinas,是的,请查看编辑。 - Nina Scholz
@NinaScholz 我从未见过如此清晰的重复示例。 - user663031
显示剩余4条评论

5

.sort()方法结合自定义函数使用时需要返回一个数字来表示哪个元素应该放在前面:

< 0 - 第一个元素必须排在第二个元素之前
   0 - 两个元素相等,不改变顺序。
> 0 - 第二个元素必须排在第一个元素之前。


通常情况下,b - a代表降序排序,a - b代表升序排序。


对元素进行排序的算法取决于浏览器对.sort()方法的实现。可以查看它们之间的比较:

enter image description here


“< 0 - 第一个元素必须放在第二个元素之前” 这句话的意思是不要改变它们的顺序吗? - Mahi
1
我可以看这些gif好几个小时 :) 很酷的例子。 - Timmetje
1
例如,选择排序的性能与数据集无关,冒泡排序在反转数据集时性能较差,对于几乎排序好的数据集,希尔排序非常快等等。此外,它看起来很整洁。 - VLAZ
2
@Mahi 不,如果某个算法使用了在 b 之后的 a,并且必须交换它们的位置。 - Justinas
1
@Timmetje 请看这个链接:https://www.youtube.com/watch?v=kPRA0W1kECg - Justinas
显示剩余7条评论

0

它将通过将其移动到该值较低或较高的位置来按减去的值对项目进行排序。

以下是一些信息:

https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort

如果提供了compareFunction,则根据比较函数的返回值对数组元素进行排序。如果正在比较的两个元素是a和b,则: - 如果compareFunction(a,b)小于0,则将a排序到低于b的索引,即a排在前面。 - 如果compareFunction(a,b)返回0,则相对于其他所有不同的元素保持a和b不变,但已排序。注意:ECMAscript标准不保证此行为,因此并非所有浏览器(例如至少可以追溯到2003年的Mozilla版本)都遵守此行为。 - 如果compareFunction(a,b)大于0,则将b排序到低于a的索引。 - 当给定特定的一对元素a和b作为其两个参数时,compareFunction(a,b)必须始终返回相同的值。如果返回不一致的结果,则排序顺序未定义。
因此,比较函数具有以下形式:
function compare(a, b) {
  if (a is less than b by some ordering criterion) {
    return -1;
  }
  if (a is greater than b by the ordering criterion) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

为了比较数字而不是字符串,比较函数可以简单地将 b 从 a 中减去。如果以下函数不包含 Infinity 和 NaN,则会升序排序数组:
function compareNumbers(a, b) {
  return a - b;
}

如果compareFunction(a, b)小于0,则将a排序到比b更低的索引,即a排在前面。这是否意味着什么都不做? - Mahi
所以可以将排序函数转换为 如果它返回正数则交换,否则不交换。吗? - Mahi
如果值与算法有关,则它所执行的操作是由算法决定的,但不一定会进行交换。在这种情况下,如果是加号,它将降低A,如果是减号,它将降低B。但至少它将降低A或降低B。唯一的情况是不执行任何操作时,值为0。 - Timmetje
@Mahi,抱歉,您不能更改它而不丧失某些排序功能。JS 可以推断出有关数据集的信息,因此不需要进行所有比较,例如 1, 2, 3 - 如果它比较 1, 2,就会发现 1 < 2;如果它比较 2, 3,就会发现 2 < 3,通过这两个事实,它可以跳过检查 1, 3,因为已经暗示着 1 (< 2) < 3。如果您的排序算法表示 2 和 3 相等(return 0),那么根据数据集如何遍历,从排序中得到的信息也可能是不正确的 - 您可能最终得到一个数组 [2, 1, 3] - VLAZ
这些内容都直接来自于https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Array/sort,并进行了相应的编辑。此外,Mozilla的评论是正确的,例如:`if (" " > 0)`虽然不完全相同,但它将返回0。 - Timmetje
显示剩余3条评论

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