数组的排序是面试以及实际应用中都会经常用到的知识点。除了被我们熟知的冒泡排序,快速排序等排序算法之外,js中也封装了相应的API以供调用。
arr.sort()对数组中的元素进行排序,直接操作原数组,默认为升序排列。
下面会对sort()的具体用法,在不同场景下的区别,具体的实现原理进行介绍。以及如何根据已知的方法对数组进行无序排列。
当数组中的元素为字符时:1
2
3var arr = ['b', 'e', 'd', 'a'];
arr.sort();
console.log(arr); //["a", "b", "d", "e"]
当数组中的元素为数字时:1
2
3var arr = [5, 8, 2, 6, 1];
arr.sort();
console.log(arr); //[1, 2, 5, 6, 8]
当直接调用arr.sort()方法时,默认为按照ASCII码对数组中的元素进行排列
所以下面的情况可能会与我们想要得到的结果有差异:1
2
3var arr = [10, 5, 8, 2, 61, 1];
arr.sort();
console.log(arr); //[1, 10, 2, 5, 61, 8]
此时比较时,会取出数组中每个元素的第一位依次比较。第一位不同时,按ASCII排列。第一位相同,再比较第二位。
所以从以上例子我们可以得到如下结论:
直接调用arr.sort()方法进行比较时,比较的是ASCII值,与数字位数无关
那么如果我们想不论数字位数,直接根据数字大小进行排序;或者是对数组进行降序排列应该怎么处理呢?
arr.sort()中可以传入一个回调函数用来对数组中的元素进行处理。原理如下:
当function返回值为负数时,两个相比较的数,前面的数在前(两个数不交换顺序);
当function返回值为正数时,两个相比较的数,后面的数在前(两个数要交换顺序)。
按照上面的原理,我们进一步探索sort方法:1
2
3
4
5
6
7
8
9
10var arr = [10, 5, 8, 2, 61, 1];
arr.sort(function (a, b) {
if(a > b) {
return 1;
}else {
return -1;
}
})
console.log(arr); // [1, 2, 5, 8, 10, 61]
当a > b时,返回正数,两个数交换顺序,将小的数(b)放在前面。
你可能会奇怪上面并没有提到当两个数相等时该如何处理?
返回去看上面的代码,当a == b时,if条件不成立,进入else,返回负数,两个数不交换顺序。
当a > b时,a - b > 0;所以上面的代码还可以进行以下修改:1
2
3
4
5
6
7
8
9
10var arr = [10, 5, 8, 2, 61, 1];
arr.sort(function (a, b) {
if (a - b > 0) {
return a - b; //此时a - b为正数
}else {
return a - b; //此时a - b为负数
}
})
console.log(arr); //[1, 2, 5, 8, 10, 61]
实现的原理为:
第一个数依次和后面的数比较,找到最小的数放在第一个;
第二个数依次和后面的数比较,找到第二小的放在第二个;
依次类推,直到元素有规律排列为止。
按照上面的原理,会发现他其实和选择排序的原理是一样的。
选择排序的原理:
数组里面的第一个数依次和后面的数作比较,如果后面的数小于第一个数,交换顺序(找出最小的放在第一位);
再选出第二个数依次和后面的数作比较,选出余下数组里面最小的放在第二位;
重复以上规律,直到数组有序为止。
具体实现如下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16var arr = [10, 5, 8, 2, 61, 1];
function selectSort (arr) {
var temple;
for (var i = 0; i < arr.length - 1; i++) { //取出数组每一位
for (var j = i + 1; j < arr.length; j++) { //循环次数
if (arr[i] > arr[j]) {
temple = arr[i];
arr[i] = arr[j];
arr[j] = temple;
}
}
}
return arr;
}
console.log(selectSort(arr)); //[1, 2, 5, 8, 10, 61]
综上所述,最终可以把arr.sort()总结为:
(1)默认对字符进行排序,直接调用arr.sort();
(2)升序排列(从小到大)1
2
3arr.sort(function (a, b) {
return a - b;
})
(3)降序排列(从大到小)1
2
3arr.sort(function (a, b) {
return b - a;
})
应用:将数组乱序排列,每次乱序的结果不一致。具体实现如下:1
2
3
4
5
6
7var arr = [10, 5, 8, 2, 61, 1];
setInterval(function () {
arr.sort(function (a, b) {
return Math.random() - 0.3;
})
console.log(arr);
}, 500)
运算结果如下:
Math.random()产生随机数,随机数的范围为[0, 1);当Math.random() - 0.5,随机数的范围为[-0.5, 0.5)。
调用arr.sort(),当返回正数时,a, b交换顺序;返回负数时,a, b顺序不变。