javaScript数组方法 Array.sort()方法剖析

1,009 阅读3分钟

Array.sort()方法MDN的部分说明

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

语法

arr.sort([compareFunction])

Array.sort() demo

const months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]

const array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]


Array.sort()方法使用说明

  1. 不传任何参数
   arr = [7, 10, 6, 8, 5]
   console.log(arr.sort())    //[10, 5, 6, 7, 8]

怎么不按套路出牌,这不是我想要的结果……别急,我们可以定义任意规则,让它按照我们想要的结果排序。 默认是按ASK码排序,10识别不是数字十,而是,1和0,按位对比,如果第一位相等,则进行下一位的对比。

  1. 传入一个函数作为参数,自定义排序规则

sort方法可以传一个function,来定义我们需要的排序规则

 arr.sort(function (a, b){
        //自定义规则
    })
  • 必需写两个形参
  • 函数返回值决定升序还是降序
    • 当返回值为负数或零时,位置不变

    • 返回值为正数时,位置调换位置


Array.sort()方法的内部原理分析

来看下面的例子

    arr = [7, 10, 6, 8, 5]
    
    arr.sort(function (a, b) {
        return a - b
    })
    console.log(arr)    

假设b >= a,此时a - b <= 0 ,返回值为负数或零,参数位置不变,也就是说大的数b排在后面,排序结果为升序

假设a > b,此时a - b > 0 ,返回值为正数,参数位置调换,也就是说ab位置调换,大的数a排在后面,结果为升序

排序过程使用原地算法,过程如下:

第一轮:

[7, 10, 6, 8, 5]

  1. 首先,数组第一位跟第二位对比,a = 7 ,b = 10return a - b为负,位置不变。数组为 [7, 10, 6, 8, 5]

  2. 接下来,数组第一位与第三位对比,a = 7 ,b = 6,return a - b为正数,调换位置,数组变为 [6, 10, 7, 8, 5]

  3. 其次,数组的第一位与第四位对比,a = 6,b = 8,return a - b为负数,位置不变,数组为 [6, 10, 7, 8, 5]

  4. 最后,数组的第一位与第五位对比,a = 6,b = 5,return a - b为正数,位置调换,数组变为 [5, 10, 6, 8, 7]

第一轮结束,最小的数变到了第一位

第二轮

[5, 10, 6, 8, 7]

  1. 首先,数组第二位跟第三位对比,a = 10 ,b = 6return a - b为正,位置调换。
  2. 然后第三位与第四位对比,以此类推。

第二轮结束第二小的数变到了第二位。第三轮结束,第三小的数换到了第三位……


Array.sort()方法源码实现

Array.prototype.mySort = function (fn = defaultFn) {
  var len = this.length
  var tmp

  for (let i = 0; i < len - 1; i++) {
    for (let j = i + 1; j < len; j++) {
      if (fn(this[i], this[j]) > 0) {
        tmp = this[i]
        this[i] = this[j]
        this[j] = tmp
      }
    }
  }
  return this
}

function defaultFn(cur, next) {
  if (String(cur) > String(next)) {
    return 1
  } else {
    return -1
  }
}

总结:

  • 结论
arr.sort(function (a, b){
   return a - b //升序
  // return b - a //降序
})
  • 个人的总结

什么时候升序,什么时候降序,刚开始容易混乱.只需记住,返回负数时,位置不变。把任意满足这一情况的特殊值代入,前面的大就是降序,后面的大就是升序。 (PS:当然记返回正数的情况也一样,记住一种情况,然后推导另一种情况,信息量减少了50%,不仅记得牢,还不会乱,效率提升不止50%)

function (a, b) { return a - b }

我要让返回值为负,此时b > a,(a, b)位置不变,大的值b在后面,为升序。

return b - a,要让返回值为负,此时a > b,(a, b)位置不变,大的值a在前面,为降序