当前位置: 首页 > 面试题库 >

用JavaScript排序:每个比较函数都应该有一个“返回0”语句吗?

卫皓
2023-03-14
问题内容

我最近阅读了许多有关使用JavaScript进行排序的答案,而且我经常偶然发现一个如下所示的compare函数:

array.sort(function(a,b){ a > b ? 1 : -1; });

因此,它是一个比较函数,如果a大于1则返回1,如果小于OR EQUAL TO b则返回-1
。如MDN(link)所述,比较函数也可以返回零,以确保两项的相对位置保持不变:a``b

如果compareFunction(a,b)返回0,则a和b彼此保持不变,但对所有不同元素进行排序。

因此,官方示例看起来像这样:

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

实际上,通过添加一条return 0语句,排序算法通常需要较少的迭代,并且总的运行速度更快(JSPerf)。

所以我想知道省略return 0声明是否有任何好处。

我意识到在MDN上,它还说:

注意:ECMAscript标准不保证此行为,因此并非所有浏览器(例如,至少可追溯到2003年的Mozilla版本)都遵守此规定。

指的是该行为,如果返回0
ab则应保持不变。因此,也许通过返回0,我们在不同的浏览器中得到了稍微不同的排序数组?这可能是原因吗?还有其他根本不归零的良好理由吗?


问题答案:

所以我想知道省略return 0语句是否有任何优势。

少键入字母。由于省略了一个比较,因此可能会快一点。所有其他影响都是 不利的

我意识到在MDN上,它还说:

注意:ECMAscript标准不保证此行为,因此并非所有浏览器(例如,至少可追溯到2003年的Mozilla版本)都遵守此规定。

参照行为,如果返回0,则a和b应该保持不变。

这位置ab可以保持不变,只是针对需求排序稳定。这不是指定的行为,某些浏览器已实现了非稳定的排序算法。

但是,返回零的实际目的是既不a进行排序b(如小于0)也不进行b排序a(如大于0)-基本上在aequals时b。这是 进行比较
必备条件 ,所有排序算法均应遵守。

为了产生有效的,令人满意的排序(数学上:将项目划分为完全排序的等效类),比较必须具有某些属性。在规范sort中列出了它们,以作为“ 一致比较功能 ”的要求。

最突出的是自反性,要求一项a等于a(本身)。另一种说法是:

compare(a, a) 必须总是回来 0

当比较函数不满足此要求时(就像您偶然发现的函数那样),会发生什么?

规格说

如果comparefn[…]不是此数组元素的一致比较函数,则行为sort是实现定义的。

这基本上意味着:如果提供的比较函数无效,则数组可能无法正确排序。它可能会随机排列,或者sort调用甚至可能不会终止。

因此,也许通过返回0,我们在不同的浏览器中得到了稍微不同的排序数组?这可能是原因吗?

不,通过返回0,您将在浏览器中获得 正确排序的
数组(由于排序不稳定,可能会有所不同)。原因是,如果不返回0,您将获得稍微不同的置换数组(如果有的话),甚至可能会产生预期的结果,但通常采用更复杂的方式。

那么,如果您不为相等的项目返回0,会发生什么?一些实现对此没有问题,因为它们从不将一个项目与其自身进行比较(即使在数组中的多个位置上都是明显的)-可以优化这一点,并且在已知结果必须为0。

另一个极端是永无止境的循环。假设彼此之间有两个相等的项目,则可以将后者与前者进行比较,并意识到您必须交换它们。再次测试,后者仍然比前者小,您必须再次交换它们。等等…

但是,高效的算法通常 不会 再次
测试已比较的项目,因此通常实现会终止。尽管如此,它可能会进行实际上不必要的或多或少的交换,因此比使用一致的比较功能所花费的时间更长。

还有其他根本不归零的良好理由吗?

懒惰并希望该数组不包含重复项。



 类似资料:
  • 问题内容: 我写的是,我正在使用Netbeans向每个函数添加类似专业的注释。因此,我从每一个开始,然后按来让Netbeans完成用于以下功能的默认注释方案。 到现在为止,我一直只在PHP语言中使用它,在这种情况下,如果遵循PHP函数确实包含了声明,则Netbeans始终仅在注释方案中添加部分。在所谓的“过程”(不返回任何值的函数)上,缺少此部分。 今天,我为Javascript函数尝试了同样的事

  • 问题内容: 我总是成功地对数组进行如下排序(当我不希望使用标准字典顺序时): 现在,有人告诉我这是错误的,我需要代替。是真的,如果是,为什么呢?我已经测试了比较功能,并且可以正常工作!此外,为什么我的解决方案错了会如此普遍? 问题答案: 我总是这样成功地排序我的数组 不,你没有。并没有注意到它。一个简单的反例: 为什么? 因为即使大于,比较函数也确实会返回(或等效地)。但是暗示着这两个元素被认为是

  • 问题内容: 从请求返回之前,我有一些异步方法需要等待完成。我正在使用Promises,但我不断收到错误消息: 为什么这令人高兴?这是我的代码: 问题答案: 只要避免构造函数反模式-promise-construction-antipattern-and-how-to-avoid- it)!如果您不调用而是返回一个值,那么您将需要进行一些操作。该方法应该用于链接:

  • 作为在正常情况下使用内置问题的后续,我进行了一些测试,并遇到了令人惊讶的结果。 我在这里比较了传统的< code>import语句和对< code>__import__内置函数的调用的执行时间。为此,我在交互模式下使用以下脚本: 与链接的问题一样,这里是导入以及其他一些标准模块时的比较: 到目前为止,比更快。这对我来说很有意义,因为正如我在链接的帖子中所写的那样,我发现与相比,当后者导致对的调用时

  • 问题内容: 假设我们在Python 3.x中(我猜在Python 2.6和Python 2.7中也)具有以下功能: 如果运行它们,我们将得到: 这三个函数提供相同的结果(值和类型),它们似乎是等效的。 但是,其中哪个陈述更正确? 这些定义中是否有副作用? 相同的问题适用于以下情况,并返回了多个值: 在这种情况下,每个函数都返回一个 元组 ,但是我的问题仍然保持不变。 问题答案: Python中的括

  • 问题内容: 我了解主键的价值。 我了解索引的价值。 每个 MySQL表都应该有一个自动递增的主键(最好是INT字段类型)吗? 更新 @Raj More的答案似乎是最有效的。但是,我想到的问题是,此自动递增的主键ID将如何与其他表相关。例如: 表格1 表2 在上面的示例中,消费者可以来到该站点并选择注册免费的产品/服务。如果消费者选择,他们可以提供其他信息(存储在表2中)以进行其他邮件发送等。我看到