sort函数如何在JavaScript中工作,以及compare函数

时间:2011-07-04 06:17:42

标签: javascript

正如已经提到的那样:排序功能如何在JavaScript中运行,以及compare功能? 如果我有一个数组,并且我array.sort(compare)现在在书中写道,如果compare函数返回a-b(数组的两个索引),那么它根据事实工作结果是否大于0,小于0或等于0.但是,它究竟是如何工作的?我无法解决这个问题。

7 个答案:

答案 0 :(得分:127)

“比较”功能必须有两个参数,通常称为 a b 。然后根据这些值 a b 使比较函数返回0,大于0或小于0。

  1. 如果 a 大于 b
  2. ,则返回大于0
  3. 如果 a 等于 b
  4. ,则返回0
  5. 如果 a 小于 b ,则返回少于0
  6. 使用这三个返回值,并且只有两个参数,可以编写一个比较函数,可以对任何类型的输入数据类型或复杂数据结构进行排序。

    然后,当您使用自定义比较函数调用sort()时,将在待排序列表中的对上调用compare函数,以确定正确的排序。

    让我们来看一个简单的例子......假设你只是对一些数字进行排序,所以我们有一个非常简单的比较函数:

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

    如果a大于b,则简单地从a中减去b将始终返回大于0,如果它们相等则返回0,如果a小于b,则小于零。所以它符合比较功能的要求。

    现在让我们假设这是我们要排序的数字列表:

    var numbers = [1,5,3.14];
    

    当你致电numbers.sort(compare)时,它会在内部实际执行:

    compare(1,5);     // Returns -4, a is less than b
    compare(1,3.14);  // Return -2.14, a is less than b
    compare(5,3.14);  // returns 1.86, a is greater than b
    

    如果您曾经进行过手动排序或字母顺序排列,那么您可能完全做了同样的事情,可能没有意识到这一点。即使您可能需要比较几十个或几百个项目,但您一次只能比较两个数字(或作者姓氏或其他)。再次查看三个数字的简短列表,首先要比较前两个数字:

    1. 1大于或小于5?小于,所以把这两个数字放在我们的列表中:1,5
    2. 3.14大于或小于1?大于,所以它在新列表中的1之后
    3. 我们的新名单中3.14是大于还是小于5?不到,所以它在5之前。我们的新列表现在是[1,3.14,5]
    4. 因为您可以提供自己的compare()函数,所以可以对任意复杂的数据进行排序,而不仅仅是数字。

答案 1 :(得分:28)

默认情况下,数组sort()方法按字母顺序按升序排序。如果您想按其他顺序排序,因为您的数组包含数字或对象,那么您可以将函数传递给sort()

传入的函数有两个参数,通常称为a和b,并返回:   如果第一个参数应该在第二个参数之前排序,则为负数(a< b)   如果参数相等则为0(a == b)   如果第一个参数应该在第二个参数(a> b)

之后排序,则为正数

现在,这里是关键位:作为参数传递给sort()的函数将由sort()重复调用,因为它处理整个数组。 sort()不知道或不关心数组中事物的数据类型:每次需要知道“项目A是否在项目B之前?”它只是调用你的功能。你不必担心sort()在内部使用什么类型的排序算法,实际上一个浏览器可能会使用不同的算法到另一个浏览器,但这没关系,因为你必须提供一种方法来比较任何算法。你的数组中的两个项目。

你的函数可以有一个if / else if / else结构来决定返回什么结果,但是对于数字,简单地返回(ab)将为你实现这个,因为减法的结果将是-ve,0或+ ve和正确地将数字按升序排列。返回(b-a)会让他们下降:

  var sortedArray = myArray.sort(function(a,b){
                                    return (a-b);
                                });

如果您有一个对象数组,并且想要对对象的某些特定属性或属性进行排序,那么您也可以这样做。假设,例如,这种格式的对象:

{ id : 1,
  name : "Fred",
  address : "12 Smith St",
  phone : "0262626262" }

然后你可以通过'id'属性对这些对象的数组进行排序,如下所示:

var sortedArray = myArray.sort(function(a,b){
                                  return (a.id - b.id);
                              });

或者您可以通过“名称”属性(按字母顺序排序)对这些对象的数组进行排序,如下所示:

var sortedArray = myArray.sort(function(a,b){
                                   if (a.name < b.name)
                                      return -1;
                                   else if (a.name == b.name)
                                      return 0;
                                   else
                                      return 1;
                               });

请注意,在我的最后一个例子中,我已经提到了我之前提到的完整if / else if / else结构。

对于使用多个属性对对象进行排序的示例,您可以进一步扩展以包含辅助排序,即(在我的示例中)如果名称属性相等,则可以返回比较,例如,电话财产。

答案 2 :(得分:5)

此方法使用Array.sort(compareFunction,sortOptions)顺序的语法和参数,其参数定义如下:

compareFunction - 用于确定数组元素排序顺序的比较函数。此参数是可选的。比较函数应该用于比较两个参数。给定元素的A和B,compareFunction的结果可以是负值,0或正值:

如果返回值为负,则表示A在排序序列中出现在B之前。 如果返回值为0,则A和B具有相同的排序顺序。 如果返回值为正,则表示A在排序序列中出现在B之后。

答案 3 :(得分:1)

  

sort方法单独将数字视为字符串,因此如果字符串数组不需要比较函数。   但是如果是数组,你需要比较函数来改变sort方法的构建行为。

ex1:字符串

var animals = ["Horse", "Cat", "Tiger", "Lion"];  
animals.sort();

ex2:数字

var marks = [70, 90, 60, 80 ];  
marks.sort(function(a, b){return a > b}); //ascending , a < b descending . 

答案 4 :(得分:1)

您现在可以使用Uint32Array创建数组。

[https://i.stack.imgur.com/qBgvm.png]

但是,它有一些困难。例如,您不能向该数组添加新值。简单来说,您无法修改数组长度。

答案 5 :(得分:1)

我们可以简化按正常顺序倒序

排序的过程

第一个参数 a

第二个参数 b

function compare(a, b) {
  //  make some operations to calculate these variables as true or false
  //     weNeedToMoveFirstParameterInPositiveDirection
  //     weDoNotNeedToMove
  //     weNeedToMoveFirstParameterInNegativeDirection

  // just think about numerical axis <------(-1)---(0)---(1)------>
  if (weNeedToMoveFirstParameterInPositiveDirection) return 1;  
  if (weDoNotNeedToMove) return 0; 
  if (weNeedToMoveFirstParameterInNegativeDirection) return -1;  
}

答案 6 :(得分:0)

我认为可能是这样的(好吧,我对此不太确定。):

假设函数compare(a,b)是比较函数。 它返回c。 假设我们要对数组N中的条目进行排序,以获得排序结果数组M

我不知道确切的排序算法,如果c既不是(a-b)也不是(b-a),那么不同的浏览器甚至会返回不同的结果(例如,如果c是{ {1}},"b-2"或其他一些表达方式。)

但是根据"a+b",排序结果应该是这样的:

a,b可以是任何两个索引。 这意味着我们实际上将一个有序对传递给compare函数。 ECMA-262

ECMAScript语言规范说结果应该具有以下属性: eg: (0,1),(1,4), or even (2,0) , (2,1)是传递给比较函数的有序对。

  • 如果(a,b)(函数返回的内容)小于零,则必须满足c

规范没有说明如果c为零或大于零会发生什么。

我不确定这是否正确。 至少这可以很容易地解释为什么当M(a)< M(b)c时,条目按数字和升序排序,以及为什么当"a-b"c时,条目被排序为相反。

浏览器的js引擎是不是严格按照`ECMA-262设计的,还是我完全错了?

参考:

The Fifth Edition of ECMA-262 (Check page 129-130)