正确使用 sort() 方法

更新日期: 2019-07-24阅读: 2k标签: 数组

在过去的几个星期里,我们在不同的团队中看到,一般来说都没有使用 Array.prototype.sort() 的习惯,并且不知道这种方法是如何工作的。今天我们将尝试简要描述它是如何工作的 .sort(),揭示它的一些秘密。


1. 修改原数组

在这种情况下,我们必须记住,此方法通过对数组进行排序来修改数组返回相同的有序数组,但不返回新数组。如果我们想要保持数组不可变并获得另一个排序,这一点很重要,我们必须在排序之前制作数组的拷贝。


2. 字符串在 Unicode 代码中的位置比较

默认情况下,.sort() 方法会根据 Unicode 代码中每个字母的位置将数组值排序为字符串,因此您可以对此数组进行排序而不会出现问题:

console.log(["Zaragoza", "Madrid", "Barcelona"].sort());
// [ 'Barcelona', 'Madrid', 'Zaragoza' ]

这似乎是正确的,但是如果和一些名称以小写字母开头,那么排序似乎不正确:

console.log(["Zaragoza", "madrid", "Barcelona"].sort());
// [ 'Barcelona', 'Zaragoza', 'madrid' ]

在这种情况下,排序是在 Unicode 代码表中的每个字母的位置之后完成的,并且 m 落后 Z ,因此它已经以这种方式排序。

如果我们想对数字排序,事情就会变得复杂起来:

console.log([80, 9, 100].sort());
// [ 100, 80, 9 ]

结果似乎很荒谬,但这是有道理的,发生的事情是数字已被转换为字符串,因此被比较的是字符串"100","80"并且"9"。由于它们在 Unicode 代码中的位置是按顺序的,因此排序是正确的,即使它不是我们最初的预期。

这些情况的产生导致一些人放弃使用 .sort() 产生混乱的行为。这有点草率,因为只需一点帮助,这种方法可以毫无问题地运行。


3. Sort() 方法参数

该 .sort() 有一个可选参数允许此方法帮助对内容进行排序。这是此方法的关键,因为我们对每种情况都感兴趣。

函数接收两个要比较的值,因此也会有这么三种情况:

  • 如果第一个值大于第二个值,则返回正值 (1);
  • 如果第一个值小于第二个值,则返回负值 (-1);
  • 如果两个值相等或等效于排序,则返回零值 (0);

这个函数由 Javascript 调用,只要您需要对数组中的元素进行排序,我们就可以进行必要的比较和调整。例如,为了比较数字,我们可以使用类似方法:

console.log([80, 9, 100].sort((a, b) => a - b));
// [ 9, 80, 100 ]

另外,(a, b) => a – b 还可以这么使用:使用其中一个值 a 去判断是否大于另一个值 b 来返回排序结果:

const data = [ "Zaragoza", "madrid", "Barcelona" ];
data.sort ((a, b) => a.toLowerCase () > b.toLowerCase ());
console.log (data);
// [ 'Zaragoza', 'madrid', 'Barcelona' ]

显然结果不正确,因为我们草率的将函数比较的结果 true 或者 false 返回,我们必须记住支持函数 .sort() 希望我们返回 -1 , 1 或者 0。为了使它正常运行,我们必须做修改:

const data = [ "Zaragoza", "madrid", "Barcelona" ];
data.sort ((a, b) =>
  a.toLowerCase() > b.toLowerCase() ? 1 :
  a.toLowerCase() < b.toLowerCase() ? -1:
  0
);
console.log (data);
// [ 'Barcelona', 'madrid', 'Zaragoza' ]

现在的结果是我们需要的,因为我们已经对小写和大写也进行了比较,并且我们已经返回-1,1或者0根据每种情况。

我们还没有真正完成,因为如果我们加入一些重音字母,我们会得到一个不希望的结果:

const data = [ "Zaragoza", "madrid", "Barcelona", "Ávila" ];

data.sort ((a, b) =>
  a.toLowerCase() > b.toLowerCase() ? 1 :
  a.toLowerCase() < b.toLowerCase() ? -1:
  0
);
console.log (data);
// [ 'Barcelona', 'madrid', 'Zaragoza', 'Ávila' ]

当我们想对文本字符串进行排序,就非常有必要使用 .localeCompare() 方法,也是非常重要。


4. 用对象属性排序数组

通常,如果数组包含对象,我们可以使用对象的属性进行比较,例如:

const data = require ('./municipios.json');
data.sort ((a, b) => a.municipio.localeCompare (b.municipio));

我们可以对数据结构中的日期和任何其他类型的对象执行相同的操作。


5. 关于性能方面

如果我们想对非常大的数组进行排序,我们必须记住。sort() 方法的支持函数将被多次调用,我们必须避免在这个函数中执行许多操作或非常重的操作。我们必须尽可能有效地进行比较。

例如,在非常大的数组中,可以使用新的方法 Int.Collate().compare 来获得更有效的排序函数,而不是使用 .localecompare()。Int 对象是名为 International api ,也是 ECMA-402 的标准的一部分,

该标准侧重于国际化功能,包括每种语言的正确排序。Int 在浏览器和节点中以全局对象的形式呈现,并具有广泛的支持(包括IE11)。

const data    = [ "Zaragoza", "Ávila", "madrid", "Barcelona" ];
const compare = new Intl.Collator ().compare;
data.sort (compare);
console.log (data);
// [ 'Ávila', 'Barcelona', 'madrid', 'Zaragoza' ]

排序操作很复杂,性能也很差,因此对于非常大的数组,排序方法支持函数速度的任何改进都将对性能产生非常显著的影响。


6. 总结

一般来说,我们应该利用 .sort() 功能和一个支持函数来控制排序应该如何执行:

  • 数字: (a, b) => a – b
  • 链式: (a, b) => a.localeCompare(b)

在没有函数参数的情况下使用 .sort() 是没有意义的,也许在少数情况下是这样,但是如果我们用一个简单的函数支持它,那么 .sort 是一个非常有用的工具

在许多情况下,排序是一个基本的操作,我们不应该放弃在Javascript中进行这种排序。


英文原文: 《Usar correctamente el método sort()》 
注意:内容有做精简和调整。 
本文首发在 pingan8787个人博客


链接: https://www.fly63.com/article/detial/4349

探索JavaScript数组奥秘

avaScript数组同后端语言一样,具有它自己的数据结构,归根结底,这种数据结构,本质就是一种集合。在后端语言中(如java,.net等),数组是这样定义的:数组是用来存储相同数据类型的集合

js使用数组+循环+条件实现数字转换为汉字的简单方法。

单个数字转汉字的解决方法:利用数组存储0-9的汉字、 ary.length和str.length不用多说,这是指ary数组和str字符串的长度。这里我们需要注意的是str.charAt(j)和ary[i],分别指在str这个字符串中索引为j的元素,在ary中索引为i的元素。

[译]async-await 数组循环的几个坑

在 Javascript 循环中使用 async/ await 循环遍历数组似乎很简单,但是在将两者结合使用时需要注意一些非直观的行为。让我们看看三个不同的例子,看看你应该注意什么,以及哪个循环最适合特定用例。

数组、字符串去重

今天说的数组和字符串去重呢,主要用到es6新的数据结构 Set,它类似于数组,但是成员的值都是唯一的,没有重复的值,所以活用Set来进行数组和字符串的去重。

JavaScript 数组方法

数组方法:1、Array.join([param]) 方法:将数组中所有的元素都转换为字符串并连接起来,通过字符 param 连接,默认使用逗号,返回最后生成的字符串2、Array.reverse() 方法:将数组中的元素颠倒顺序(在原数组中重新排列它们),返回逆序数组

如何删除JavaScript 数组中的虚值

falsy(虚值)是在 Boolean 上下文中已认定可转换为‘假‘的值.JavaScript 在需要用到布尔类型值的上下文中使用强制类型转换(Type Conversion )将值转换为布尔值,比如:在条件语句或者循环语句中。

JavaScript中十种一步拷贝数组的方法

JavaScript中我们经常会遇到拷贝数组的场景,但是都有哪些方式能够来实现呢,我们不妨来梳理一下。扩展运算符(浅拷贝)自从ES6出现以来,这已经成为最流行的方法。

JS数组的几个经典api

本文主要来讲数组api的一些操作,如简单实现扁平化n维数组、数组去重、求数组最大值、数组求和、排序、对象和数组的转化等。扁平化嵌套数组/展平和阵列孔——flat()

关于Vue不能监听(watch)数组变化

vue无法监听数组变化的情况,但是数组在下面两种情况下无法监听:利用索引直接设置数组项时,例如arr[indexofitem]=newValue;修改数组的长度时,例如arr.length=newLength

JS计算两个数组的交集、差集、并集、补集(多种实现方式)

使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本,使用 ES5 语法来实现虽然会麻烦些,但兼容性最好,不用考虑浏览器 JavaScript 版本。也不用引入其他第三方库。

点击更多...

内容以共享、参考、研究为目的,不存在任何商业目的。其版权属原作者所有,如有侵权或违规,请与小编联系!情况属实本人将予以删除!