如何让数组排序更优雅

序言

提起数组排序大家可能会觉得很简单,就是调用数组的sort就OK了, 其实真实的业务场景中排序会更加的复杂,比如说版本号排序, 姓名排序等... 今天分享一个简洁优雅的排序方式给大家, 首先大家需要知道一些前置的知识,String.localeCompareArray.sort

Array.sort

sort() 方法会对原数组的元素进行排序,并返回对相同数组的引用。默认排序是将元素转换为字符串,然后按照它们的 UTF-16 码元值升序排序。

参数

它接收一个可选参数 compareFn,同于定义排序顺序的函数。返回值应该是一个数字,其正负性表示两个元素的相对顺序。该函数使用以下参数调用:a(第一个比较元素) 以及 b(第二个比较元素)

注意, 如果省略该函数,数组元素会被转换为字符串,然后根据每个字符的 Unicode 码位值进行排序。

题外话, sort是会改变原数组的,如果你想不改变原数组排序的话, 可以使用toSorted,这个方法会返回一个新数组而不会改原数组,调用方式和 sort 是一样的。

localeCompare

相较于sort,这个api大家可能不太熟悉,这是字符串的一个api,localeCompare() 方法返回一个数字,表示参考字符串在排序顺序中是在给定字符串之前、之后还是与之相同,这个api是我们优雅实现排序的核心

参数

localeCompare() 一共有3个参数:

scss 复制代码
str1.localeCompare(str2, locales, options)
  • str1 - 要比较的第一个字符串
  • str2 - 要比较的第二个字符串
  • locales - 语言码,影响排序规则,可选
  • options - 配置对象,可包含多个选项

options 对象可以包含以下属性:

  • numeric - 是否按数字排序,默认为false
  • sensitivity - 比较字符大小写敏感度,可选值为:
    1. base(不敏感。会忽略大小写差异,'a'和'A'会被视为相等)
    2. accent (敏感度中等。会区分大小写,但会忽略某些字母变音符号的差异,比如 'e'和'é'会被视为相等)
    3. case(高度敏感。完全区分大小写,也不会忽略任何变音符号的差异。)
  • ignorePunctuation - 忽略标点符号的差异

a-z排序

了解完上述前置知识之后,我们来思考一下,如果现在有一个需求是把字符串按照 a-z 来排序,示例如下:

javascript 复制代码
const company = ['字节跳动', '网易', '拼多多', '百度', '阿里']
company.sort((a, b) => {
    // do something...
})

这里我们就要借助 localeCompare 来实现了, localeCompare 第二个参数接收一个语言码, 这里我们只需要传入中文语言码, 即可完成排序, 排序代码如下:

css 复制代码
company.sort((a, b) => a.localeCompare(b, 'zh'))

版本号排序

版本号排序其实是排序面试题中比较常见的,我们来思考一下,如果现在有一个需求是把版本号排序,示例如下:

css 复制代码
const versions = ['0.52.7.6.123', '12.5.4', '11.578.95', '0.6584.1', '0.65.83', '0.65.83.1',]
version.sort((a, b) => {})

这时候你会怎么去写这个函数呢, 一般人的思路就是把a,b两个字符串都转成数组,然后逐项比较,简洁点写出来差不多就是这样的

javascript 复制代码
versions.sort((version1, version2) => {
    const arr1 = version1.split('.').map((e) => e * 1)
    const arr2 = version2.split('.').map((e) => e * 1)
    const length = Math.max(arr1.length, arr2.length)
    for (let i = 0; i < length; i++) {
      if ((arr1[i] || 0) > (arr2[i] || 0)) return 1
      if ((arr1[i] || 0) < (arr2[i] || 0)) return -1
    }
    return 0
})

但是!上述的写法还是太繁琐了些,通过localeCompare, 其实我们一行代码就可以搞定:

css 复制代码
versions.sort((a, b) => a.localeCompare(b, undefined, { numeric: true }))

这里我们巧妙的通过配置 numerictrue来使得字符串在比较时转成数字然后去逐个比较出来最终结果用于版本号排序,实现了和上面一大串代码一样的效果。

写在结尾

平时多了解一些方法的特殊使用场景, 在真正需要用到的时候就能做到从容游刃有余。 写代码嘛, 优雅,永不过时

相关推荐
ComPDFKit31 分钟前
使用 PDF API 合并 PDF 文件
前端·javascript·macos
yqcoder38 分钟前
react 中 memo 模块作用
前端·javascript·react.js
优雅永不过时·2 小时前
Three.js 原生 实现 react-three-fiber drei 的 磨砂反射的效果
前端·javascript·react.js·webgl·threejs·three
神夜大侠4 小时前
VUE 实现公告无缝循环滚动
前端·javascript·vue.js
明辉光焱4 小时前
【Electron】Electron Forge如何支持Element plus?
前端·javascript·vue.js·electron·node.js
柯南二号4 小时前
HarmonyOS ArkTS 下拉列表组件
前端·javascript·数据库·harmonyos·arkts
wyy72935 小时前
v-html 富文本中图片使用element-ui image-viewer组件实现预览,并且阻止滚动条
前端·ui·html
前端郭德纲5 小时前
ES6的Iterator 和 for...of 循环
前端·ecmascript·es6
王解5 小时前
【模块化大作战】Webpack如何搞定CommonJS与ES6混战(3)
前端·webpack·es6
欲游山河十万里5 小时前
(02)ES6教程——Map、Set、Reflect、Proxy、字符串、数值、对象、数组、函数
前端·ecmascript·es6