[译]正确使用 sort() 方法

英文原文: 《Usar correctamente el método sort()》
注意:内容有作精简和调整。

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

1. 修改原数组

在这种状况下,咱们必须记住,此方法经过对数组进行排序来修改数组返回相同的有序数组,但不返回新数组。若是咱们想要保持数组不可变并得到另外一个排序,这一点很重要,咱们必须在排序以前制做数组的拷贝。git

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

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

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

这彷佛是正确的,可是若是和一些名称以小写字母开头,那么排序彷佛不正确:json

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() 但愿咱们返回 -11 或者 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' ]

如今的结果是咱们须要的,由于咱们已经对小写和大写也进行了比较,而且咱们已经返回-11或者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中进行这种排序。

关于我

本文首发在 pingan8787我的博客,如需转载请保留我的介绍。
Author 王平安
E-mail pingan8787@qq.com
博 客 www.pingan8787.com
微 信 pingan8787
每日文章推荐 https://github.com/pingan8787...
ES小册 js.pingan8787.com

微信公众号

bg

相关文章
相关标签/搜索