ECMAScript 2015: 如何避免 JS 排序字符串的奇怪行为

在开发过程中,我们经常需要对数据进行排序操作。对于数字和日期等非字符串类型的排序,通常仅需要使用 JavaScript 原生的 Array.sort() 方法即可。但对于字符串的排序,由于 JS 默认使用字典序进行排序,往往会出现一些意料之外的结果。本文将介绍这些奇怪的行为,并提供一些方法来避免它们。

JS 默认的字典序排序

在 JS 中,字符串的排序规则是根据 Unicode 码位的大小关系来进行比较的。例如,字符串 "a" 的 Unicode 码位为 097,而字符串 "A" 的 Unicode 码位为 065,因此在 JS 中,"A" 会排在 "a" 前面。

----- --- - ----- ------ ---- ---- ---- ------
----------- -- ----- ---- ---- ----- ------ ----

如上所示,JS 默认使用字典序进行排序。但这种方式很容易出现一些奇怪的结果。比如,数字和符号的编码顺序通常与其使用顺序不一致。示例如下:

----- --- - ------ ---- ---- ---- ----- -----
----------- -- ----- ----- ----- ---- ---- ----

按照字典序排序,"!" 和 ">" 会排在数字前面,这可能不是我们想要的结果。那么,有什么方法可以避免这种情况呢?

重写排序函数

Array.sort() 方法允许我们传入一个函数作为参数,来指定排序规则。该函数接受两个参数,表示要比较的两个元素。如果返回值小于 0,则第一个元素排在第二个元素前面,大于 0 则第一个元素排在第二个元素后面,等于 0 则两个元素相等。

通过重写排序函数,我们可以自定义排序规则,来避免字典序排序带来的问题。例如,我们可以比较元素的长度,在长度相同的情况下再逐个比较字符。这样就可以得到我们想要的结果:

----- --- - ------ ---- ---- ---- ----- -----
------------ -- -- -
  -- --------- --- --------- -
    ------ -------------------
  -
  ------ -------- - ---------
--- -- ----- ---- ----- ----- ---- ----

如上所示,在重写排序函数之后,我们得到了正确的结果。如果两个元素长度相同,则使用 a.localeCompare(b) 方法比较字符顺序;否则使用两者的长度差来决定排序顺序。

使用 Collator

从 ECMAScript 2015 开始,JS 提供了 Intl.Collator 类,用于处理字符串的排序。与 Array.sort() 方法相比,Intl.Collator 允许我们指定多个排序规则,包括排序方式(升序或降序)、是否区分大小写、是否忽略符号等。

例如,我们可以使用 Intl.Collator 来按照数字大小进行排序:

----- --- - ------ ---- ----- -----
----- -------- - --- ------------------------ - -------- ---- ---
--------------------------- -- ----- ---- ----- -----

其中,{ numeric: true } 表示按照数字大小进行排序。

若要在排序中忽略符号或区分大小写,我们可参考以下代码:

----- --- - ------ ----- ---- ----- ----- ----- -----
----- -------- - --- ------------------------ - ------------ ------- ------------------ ---- ---
--------------------------- -- ----- ---- ----- ----- ----- ----- -----

在上述示例中,我们定义了两个选项:sensitivity 表示区分大小写程度,取值包括 "base"、"accent" 和 "case";ignorePunctuation 表示是否忽略符号。

结论

JS 默认的字典序排序可能会出现一些奇怪的结果,特别是在排序字符串时。为避免这些问题,我们可重写排序函数或使用 Intl.Collator 类。

重写排序函数允许我们自定义排序规则,但需要编写一些额外的代码。Intl.Collator 类虽然更为方便,但需要考虑更多的选项,需要多花一些时间学习。

无论使用哪种方法,都需要注意避免不必要的排序操作,因为排序是一种比较耗时的操作。只在必要的时候进行排序,会提高应用的性能。

来源:JavaScript中文网 ,转载请注明来源 本文地址:https://www.javascriptcn.com/post/6706cf83d91dce0dc8629c59