【问题标题】:I don't understand WHY numerical sort functions work in Javascript [duplicate]我不明白为什么数字排序函数在 Javascript [重复]
【发布时间】:2014-02-08 21:56:07
【问题描述】:

我了解 .sort() 方法按字母顺序对数组进行排序,就好像它是一个字符串一样。即使您的数组完全由数字组成。

我也明白要对数组进行数字排序,代码是:

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

问题是我不明白为什么会这样。我写的函数应该有两个参数,'a'和'b',但是这些参数是从哪里来的呢?阵?它怎么知道这样做?然后,该函数返回一些数字。如果“a”和“b”分别为 10 和 5,我的函数将返回“5”。现在我在做 myArray.sort(5);这到底是如何神奇地对我的整个数组进行数字排序???

感谢您的帮助。

【问题讨论】:

标签: javascript arrays sorting


【解决方案1】:

我写的函数应该有两个参数,'a'和'b',但是这些参数是从哪里来的呢?

为了确定数组元素所属的顺序,Array.sort 函数从数组中挑选元素对,并将它们作为a 和b 传递给比较函数。您的函数返回的结果决定了两个元素的放置顺序 - 如果它是负数,那么它知道将 a 放在 b 之前;如果它是肯定的,它知道将a 放在b 之后。实际数字无关紧要,无论是负数还是正数。

编写示例的一种不太容易混淆的方式可能是:

function myComparisonFunction(a, b) {
    if (a < b) {
        return -1;
    }
    if (a > b) {
        return 1;
    }
    return 0;
}

myArray.sort(myComparisonFunction);

【讨论】:

  • 这是一个很好的解释,但我仍然感到困惑。你说 fit 选择成对的元素,但它是如何选择成对的呢?前任。 [1,10,9,4,2,5]。那么,这对是什么?它会像 (1,10) - (10,9) - (9,4) 那样串联,还是像 (1,10) - (1,9) - (1,4) 这样串联?
【解决方案2】:

排序函数通过(巧妙地)比较成对的数组条目来操作。根据比较的结果,它知道一对特定值的顺序。它是怎么知道的?因为它信任排序回调函数返回

  • -1(或任何负数)如果第一个条目应该在第二个之前;
  • 如果第二个条目应该在第一个之前,则为 1(或任何非零正数);
  • 0 如果条目相同(意味着顺序无关紧要*)

通过反复比较数组条目对,并系统地这样做,排序函数最终根据比较函数施加的固有规则确定整体正确的排序。

JavaScript 排序实现所使用的系统过程的性质未指定。现代 JavaScript 运行时使用相当优化的 quicksort 是一个不错的选择。

* 当数组中的两个条目根据比较函数相等时,可能会发生两件事:排序函数可能会使它们保持原来的顺序出现,或者它可能会交换它们。通过排序过程的简单逻辑,这些操作中的任何一个都可以;如果您正在对名称列表进行排序,并且“Thomas”出现了两次,那么哪个“Thomas”是第一个和哪个是第二个并不重要,因为这些字符串是相同且无法区分的。但是,如果排序比较器函数从成对的对象中提取属性,有时如果它们的比较返回 0,则条目保持原始顺序确实很重要。确保行为的排序函数称为stable。规范未定义 JavaScript 实现是否稳定。

【讨论】:

  • 我认为这对我来说最有意义,谢谢。 sort 函数通过比较数组中的两个值并通过它是否大于或小于另一个来确定它的顺序。默认情况下, .sort() 只是按字母顺序执行,除非我们用函数指定如何执行。希望这是正确的!
  • @taykcrane 是的,完全正确。内置行为是按字符串排序。您告诉它进行不同排序的方式是提供比较器功能;这样排序例程可以说“好的,这两个怎么样?应该先出现哪个?”比较器返回答案。
【解决方案3】:

现在我在做 myArray.sort(5);

那不是真的。传入(有时)返回5 的函数与传入5 完全不同。

发生的情况是,您传入一个函数,sort 可以在它需要知道两个值中的哪个值更大时调用它。 sort 会将两个参数传递给该函数。如果函数返回负值,则表示“第一个参数小于第二个参数”;如果它返回零,这意味着“两个参数应该被认为是相等的”;如果它返回一个正值,这意味着“第一个参数大于第二个参数”。 (这可能看起来有点老套和武断——也许确实如此——但它在类 C 语言中有着悠久的历史。)因此,对于数值比较,只返回 a-b 很方便,因为它符合这些要求。

请注意,您无法准确预测 sort 将决定执行哪些比较,因此您需要确保传入一个行为一致的函数。例如,如果您的函数说 1 小于 2 并且 2 小于 3,那么您的函数还需要说 2 大于 1、3 大于 2、1 小于 3 以及3 大于 1。否则,您可能会得到看似随机的结果。

(顺便说一下,您可能对the MDN page on Array.prototype.sort 感兴趣。它提供了许多其他示例,可能有助于您澄清这一点。)

【讨论】:

    【解决方案4】:

    在Array.sort(ES5 spec.,MDN)中使用的这个比较器函数应该返回一个数字,其中..

    • 如果a 小于0
    • 如果a > b,返回大于0
    • 否则(a == b)返回0

    那么,让我们看一些案例:

    a     b     a-b    meaning (see above)
    ----  ----  ----   ------
    10    5     5      "a > b"
    5     10    -5     "a < b"
    5     5     0      "a == b" 
    

    比较器函数定义了在Comparison Sort algorithm中使用的元素之间的排序:

    比较排序是一种排序算法,它仅通过单个抽象比较操作(通常是“小于或等于”运算符或三向比较 [又名“比较器”])读取列表元素,以确定两个元素中的哪一个应该首先出现在最终的排序列表中。

    (注意:Array.sort 的排序不保证为stable。)

    【讨论】:

    • 是的,是的,我知道。我修正了底部的谎言 - 需要不时刷新/纠正我的“知识”。
    【解决方案5】:

    所以它会运行并应用它想要对数组中的值进行排序的任何算法。它只需要知道如何判断哪个“更大”或哪个应该被前向索引。

    我想对 javascript 的工作原理有更多的了解会有所帮助。使用 javascript,您可以将变量分配为函数,因此您可以将函数作为参数传递。它在这种情况下和异步回调中派上用场(如果您使用过 jquery,您可能已经在 ajax 调用中看到了这一点,并且在完成各种转换后调用它们......就像如果您想要一个元素移动 500 像素,然后在完成后立即将其向下移动 500 像素,然后将向下移动功能放入回调中)。

    长话短说,a 和 b 值来自您的数组,它提取的值取决于排序函数。

    关于 sort 的比较函数最棒的地方是假设你有一个看起来像这样的对象:

    sales:[{sale:{"brand":"Nike", "person":"Eric", "total":5000}}, {sale:{...}}]
    

    您可以使用排序功能按品牌排序然后总计如下:

    sales.sort(function(a,b){
        if (a.brand==b.brand){
           return a.brand>b.brand ? 1 : -1;
        } else {
           return a.total-b.total;
    });
    

    我倾向于认为这样的东西真的很简洁......它让语言使用它感觉使用的最有效的排序算法,你所要做的就是向它展示如何确定一个是否比另一个“更大” .

    【讨论】:

      【解决方案6】:

      a 和 b 数组中要比较的两个连续值 和减法可以是0,小于零和大于零.. 如果大于零,则表示先验元素较大,因此需要进一步向下推 如果小于零,则表示不需要下推..

      【讨论】:

      • 所以我明白这一点,但我的函数的哪一部分告诉它向下推,而不是向下推等。这对我来说似乎太随意了。
      • 它可能是在javascript引擎中实现的,我们必须编写一个类似的函数来展示这个概念。
      【解决方案7】:

      在您的示例中,您没有执行myArray.sort(5);,因为您传递的是一个函数(用于指导排序算法),而不是一个数字。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2021-10-20
        • 1970-01-01
        • 2019-12-14
        • 2018-06-30
        • 2022-10-05
        • 2021-11-18
        • 2022-01-23
        • 1970-01-01
        相关资源
        最近更新 更多