JavaScript数组sort排序规则

606 阅读5分钟

背景:

又是居家办公的一天,闲来没事刷刷朋友圈。就看到了一条引人入目的标题:JavaScript的数组默认排序规则。 哟,瞬间就让摸鱼状态离体而去,学习状态立马入魂。让我来刨析这道菜。

干货:

在JavaScript的sort排序中,它可以接受一个非必传的函数。

函数:sort()

  • 作用:对数组排序
  • 参数:非必传的回调函数function(a,b){},决定排序规则。
    • 降序:从小排到大:arr.sort(function(a,b){return a-b});
    • 升序:从大排到小:arr.sort(function(a,b){return b-a});

现在我们从传函数和不传递函数两者情况来分析。

1. 不传递函数

let arr = [23,112233];
arr.sort();
//打印结果
[ 112233, 23 ]

这是为什么呢?因为在sort函数中,当我们直接调用没有传函数参数时,它的底层代码是根据数组元素内容的第一个下标值对应的 ASCII码 来排序。 像上面的例子。第一个元素内容是23,对应的第一个下标值是2,对应的 ASCII码是50;第二个元素内容是112233,对应的第一个下标值是1,对应的 ASCII码是49。因此该数组排序结果是:[ 112233,23 ]。 再来个例子

let arr = ['ast','A'];
arr.sort();
//打印结果
[ 'A', 'ast' ]

如上,a字符的ASCII码是97,A字符的ASCII码是65,所以结果如上。

2. 传递函数

sort()函数其实跟es6的高阶函数filter、find等函数相似,都接受一个回调函数作为参数,只是sort的回调函数只接受两个参数,一个是当前值,一个是后面值。 如果 当前值-后面值>0,则升序,反之是降序

下面看一下例子。

var arr = [22, 111, 3, 5, 6, 1];

//升序
arr.sort((a, b) => {
    return a - b;
})
//打印结果为:
[ 1, 3, 5, 6, 22, 111 ]

//降序
arr.sort((a, b) => {
    return b - a;
})
//打印结果为:
[ 111, 22, 6, 5, 3, 1 ]

在以上的基础上,我们就可以封装工具,来针对需要进行排序的业务功能。

下面我举了一个例子:

对于CSS的优先级处理时,我们知道 important > 内联 > id > class/伪类/属性 > 元素/为元素 > 通用 >继承样式。那么我们就可以通过sort来实现。

const rules = [
  {
    value: "类名",
    weight: 300,
  },
  {
    value: "内联",
    weight: 500,
  },
  {
    value: "id",
    weight: 400,
  },
  {
    value: "标签名",
    weight: 200,
  },
  {
    value: "通配符",
    weight: 100,
  },
];
const array = ["标签名", "通配符", "内联", "id", "类名"];
array.sort((a, b) => {
  const first = rules.find((item) => item.value == a).weight;
  const second = rules.find((item) => item.value === b).weight;
  return second - first;
});
console.log(array);
//打印结果:
[ '内联', 'id', '类名', '标签名', '通配符' ]

以上就是一个demo。当然除了sort排序之外,还要冒泡排序、选择排序、插入排序、快速排序得到。这几种排序都不会很难。直接上代码+注释

扩展:

1. 冒泡排序

从下标0开始进行两辆交换,把最大的放到数组末端

var a = [1,4,3,5,6,2,11,7];
function maopao(a){
    for(var i=a.length-1;i>0;i--){
        for(var j=0;j<i;j++){
            if(a[j]>a[j+1]){
                [a[j],a[j+1]] = [a[j+1],a[j]]
            }
        }
    }
    return a
}
console.log(maopao(a));

2. 选择排序

从起始位置开始,获取比当前起始位置的值还小的值进行互换,循环进行

var a = [1,4,3,5,6,2,11,7];
function selectList(list){
    //1.获取数组长度
    var length =list.length;    //7
    //2.外层循环:从0位置开始取出数据,直到length-1位置
    for(var i=0;i<length-1;i++){
        //3.内层循环:从i+1位置开始,和后面的进行比较
        var min =i
        for(var j=min+1;j<length;j++){
            //4.如果1位置的数据大于j位置的数据,那么记录最小的位置
            if(list[min]>list[j]){
                min=j
            }
        }
        //5.把当前循环的起点下标和最小数的下标进行互换,即把最小值放到了第一个
        [list[min],list[i]] = [list[i],list[min]]
    }
    return list
}
console.log(selectList(a));

3. 插入排序

  1. 外层循环:从第一个位置开始获取数据,向前面局部有序进行插入
  2. 内层循环:获取i位置的元素,和i-1的数据依次进行比较
  3. j位置的数据,放置temp的数 据即可
var a = [1,4,3,5,6,2,11,7,9];

//插入排序
function insertSort(list) {
    var length = list.length
    //外层循环:从第一个位置开始获取数据,向前面局部有序进行插入
    for(var i=1;i<length;i++){
        //内层循环:获取i位置的元素,和i-1的数据依次进行比较
        var temp = list[i]
        var j =i
        while(list[j-1] > temp && j>0){
            list[j] = list[j-1]
            j--
        }
        //将j位置的数据,放置temp的数据即可
        list[j] = temp
    }
    return list   
}
console.log(insertSort(a))

4.快速排序

快速排序的核心思想是分而治之,先选出一个数据(比如65),将比其小的数据都放在它的左边,将比它大的数据都放在它的右边。这个数据称为枢纽 快速排序的枢纽:

  • 第一种方案: 直接选择第一个元素作为枢纽。但是,当第一个元素就是最小值的情况下,效率不高;
  • 第二种方案: 使用随机数。随机数本身十分消耗性能,不推荐;
  • 优秀的解决方法: 取index为头、中、位的三个数据排序后的中位数;如下图所示,按下标值取出的三个数据为:92,31,0,经排序后变为:0,31,92,取其中的中位数31作为枢纽(当(length-1)/2不整除时可向下或向上取整)
//交换函数
let swap = function (arr, m, n) {
  [arr[m], arr[n]] = [arr[n], arr[m]];
};
//枢纽函数
let median = function (arr) {
  let left = 0;
  let right = arr.length - 1;
  let center = Math.floor((left + right) / 2);
  if (arr[left] > arr[center]) {
    swap(arr, left, center);
  }
  if (arr[center] > arr[right]) {
    swap(arr, center, right);
  }
  if (arr[left] > arr[center]) {
    swap(arr, left, center);
  }
  return center;
};
//快速排序
let QuickSort = function (arr) {
  if (arr.length == 0) {
    return [];
  }
  let center = median(arr);
  let c = arr.splice(center, 1);
  let l = [];
  let r = [];

  for (let i = 0; i < arr.length; i++) {
    if (arr[i] < c) {
      l.push(arr[i]);
    } else {
      r.push(arr[i]);
    }
  }
  return QuickSort(l).concat(c, QuickSort(r));
};

let arr = [0, 13, 81, 43, 31, 27, 56, 92];
console.log(QuickSort(arr));

总结:

以上就是今天的内容,要是有优化的空间可以私聊我,下班去咯。