sort方法原理与手写sort方法

757 阅读2分钟

sort的使用

arr.sort([compareFunction])

  • sort默认是对元素的Unicode位进行排序,若第一个字符一样就对比第二个字符
  • sort会改变原数组
  • sort接收一个函数作为参数,这个函数可以用来改变排序规则
    • 函数会被执行多次(根据对比次数)
    • 函数接收两个参数,这两个参数分别是原数组中参与对比的两项
    • 函数参数fn(a,b)的返回值小于0,a在b之前,整体看就是倒序
    • 函数参数fn(a,b)的返回值大于0,b在a之后,整体看就是正序
    • 函数参数fn(a,b)的返回值不小于也不等于0,不改变ab的顺序

对字符串进行排序

let arr = ['hh','a','aaa']
arr.sort((a,b)=>{
  console.log(a,b)  // a hh    这里注意a,b的值并不是顺序取的
                    // aaa a
})
console.log(arr)  // 函数没有返回值,所以顺序不变

arr.sort((a,b)=>{
  console.log(a,b)  // a hh ;aaa a
  return -1   // 固定返回负数,所以参数a b顺序不变,也就是倒序
})
console.log(arr)   // ['aaa', 'a', 'hh']

对数字进行排序

let arr = [12,3,43,5,21,111]
arr.sort()
console.log(arr)  // 按照unicode排序,[111, 12, 21, 3, 43, 5]
arr.sort((a,b)=>a-b)  // 从小到大排列
console.log(arr)  // [3, 5, 12, 21, 43, 111]
arr.sort((a,b)=>b-a)   // 从大到小排列
console.log(arr) //[111, 43, 21, 12, 5, 3]

对对象进行排序

  • 由于在函数参数中可以接收每一项元素,也就可以根据每一项的内容来制定排序规则
let arr = [
  { name: 'b', age: 11 },
  { name: 'aa', age: 61 },
  { name: 'a', age: 16 },
  { name: 'c', age: 8 },
]
arr.sort((a, b) => {
  if (a.name > b.name) return 1
  if (a.name < b.name) return -1
  return 0
})  // 根据名字的Unicode排序
console.log(arr)  
    // 0: {name: 'a', age: 16}
    // 1: {name: 'aa', age: 61}
    // 2: {name: 'b', age: 11}
    // 3: {name: 'c', age: 8}
arr.sort((a, b) =>a.age-b.age)  // 根据年龄大小排序
console.log(arr)  
    // 0: {name: 'c', age: 8}
    // 1: {name: 'b', age: 11}
    // 2: {name: 'a', age: 16}
    // 3: {name: 'aa', age: 61}

手写sort

  • 此处只以插入排序为例
// 在数组原型上自定义sort方法
Array.prototype.customSort = function (fn) {
  let arr = this  // this就是原数组
  let len = arr.length
  let cur, preIndex
  // 采用插入排序的方式
  for (let i = 1; i < len; i++) {
    cur = arr[i]
    preIndex = i - 1
    // fn不存在,将数字会转换为字符串,对比unicode位
    // fn 存在,执行fn,将结果与0做比较
    while (preIndex >= 0 && (fn ? fn(cur, arr[preIndex]) < 0 : 
                                cur.toString() < arr[preIndex].toString())) {
      arr[preIndex + 1] = arr[preIndex]
      preIndex--
    }
    arr[preIndex + 1] = cur
  }
  return arr
}
// test 1
let arrTest = [
  { name: 'b', age: 11 },
  { name: 'aa', age: 61 },
  { name: 'a', age: 16 },
  { name: 'c', age: 8 },
]
arrTest.customSort((a, b) => b.age - a.age)
console.log(arrTest)  // 按年龄倒序
// test 2
let arrTest = [12, 3, 43, 5, 21, 111]
arrTest.customSort((a, b) => b - a)
console.log(arrTest)  // 倒序 [111, 43, 21, 12, 5, 3]
// test 3
let arrTest = [12, 3, 43, 5, 21, 111]
arrTest.customSort()
console.log(arrTest)  // unicode排序 [111, 12, 21, 3, 43, 5]
// test 4
let arrTest = [12, 3, 43, 5, 21, 111]
arrTest.customSort(()=>-1)
console.log(arrTest)  //  参数固定返回-1,所以颠倒原数组 [111, 21, 5, 43, 3, 12]