JS排序:中文和数字混合排序实现

1,457 阅读2分钟

问题:对数组 ['张三1','张三2','张三5','张三13','张三24','张三3','张三17','张三19'] 升序排列

提到排序,首先想到sort()方法

const strArr = ['张三1','张三2','张三5','张三13','张三24','张三3','张三17','张三19']
strArr.sort()

//输出结果如下
['张三1', '张三13', '张三17', '张三19', '张三2', '张三24', '张三3', '张三5']

输出的结果并非想要的结果,究其原因

sort()  方法用原地算法对数组的元素进行排序,并返回数组。默认排序顺序是在将元素转换为字符串,然后比较它们的 UTF-16 代码单元值序列时构建的。


arr.sort([compareFunction])

比较函数如下

function compare(a, b) {
  if (a < b ) {           // 按某种排序标准进行比较,a 小于 b
    return -1;
  }
  if (a > b ) {
    return 1;
  }
  // a must be equal to b
  return 0;
}

strArr.sort((a,b)=>{
    a.localeCompare(b)
})
//输出结果如下
['张三1', '张三2', '张三5', '张三13', '张三24', '张三3', '张三17', '张三19']

输出的结果依旧是并非想要的结果,查阅(MDN Web Docs (mozilla.org))关于localeCompare用法(以下摘自MDN):

referenceStr.localeCompare(compareString[, locales[, options]])
  • compareString: 用来比较的字符串

  • locales:可选参数, string | string[], 可选。用来表示一种或多种语言或区域的一个符合

  • options: 可选。

    • localeMatcher

      地域匹配算法的使用。可能的值是 "lookup" 和 "best fit"; 默认的值是 "best fit"

    • usage

      指定比较的目标是排序或者是搜索。可能的值是 "sort" 和 "search";默认是 "sort".

    • sensitivity

      指定排序程序的敏感度(Which differences in the strings should lead to non-zero result values.)可能的有:

      • "base": 只有不同的字母字符串比较是不相等的。举个例子: a ≠ ba = áa = A.
      • "accent": 只有不同的字母或读音比较是不相等的。举个例子: a ≠ ba ≠ áa = A.
      • "case": 只有不同的字母或大小写比较是不相等的。举个例子: a ≠ ba = áa ≠ A.
      • "variant": 不同的字母或读音及其它有区别的标志或大小写都是不相等的, 还有其它的差异可能也会考虑到。举个例子: a ≠ ba ≠ áa ≠ A.

      The default is "variant" for usage "sort"; it's locale dependent for usage "search".

    • ignorePunctuation

      指定是否忽略标点。可能的值是 true and false; 默认为 false.

    • numeric

      是否指定使用数字排序,像这样 "1" < "2" < "10"。可能的值是 true 和 false;默认为 false。这个选项能被通过options 属性设置或通过 Unicode 扩展。假如两个都被设置了,则 options 优先。实现不用必须支持这个属性。

    • caseFirst

      指定大小写有限排序。可能的值有 "upper""lower" 或 "false" (use the locale's default); 默认为 "false". 这个选项能被通过 options 属性设置或通过 Unicode 扩展。假如两个都被设置了,则 options 优先。实现不用必须支持这个属性。

//方法一
strArr.sort((a, b) => {
    return a.localeCompare(b, 'zh-Hans-CN', { numeric: true })
})

//方法二
const collator = new Intl.Collator('zh-Hans-CN', { numeric: true });
strArr.sort((a, b) => {
    return collator.compare(a, b)
})

//输出结果
['张三1', '张三2', '张三3', '张三5', '张三13', '张三17', '张三19', '张三24']

完美解决!;-)