JS中sort方法详解
sort() 方法用于对数组的元素进行排序,并返回排序后的数组。默认排序顺序是根据字符串Unicode码点(注意这里不是按ASCII编码排序,这里按Unicode编码排序要和平常两个字符串的<,>,<=,>=,一位位字符按ASCII编码排序区分开。)
语法:arrayObject.sort(func);参数func可选,规定排序顺序,必须是函数。
注:如果调用该方法时没有使用参数,将按字母顺序对数组中的元素进行排序,说得更精确点,是按照Unicode字符编码的顺序进行排序。要实现这一点,首先应把数组的元素都转换成字符串(如有必要),以便进行比较。
eg:
1 | var scores = [1, 10, 21, 2]; |
如果想按照其他标准进行排序,就需要提供比较函数,该函数要比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数 a 和 b,其返回值如下:
如果返回一个负数,则第一个参数应该排列在前面,即在排序后的数组中 a 应该出现在 b 之前。
如果 返回 0,表示a 等于 b,则a 和 b 的相对位置不变。(注意这里和排序算法的稳定性有关)
如果返回一个正数,则第二个参数应该排列在前面。
所以,比较函数格式如下:
1 | function compare(a, b) { |
要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列:
1 | function compareNumbers(a, b) { |
你可能还有疑问,就是为什么比较函数要放两个参数?我们可以拿V8引擎(Chrome浏览器的JS引擎)来理解。
V8引擎使用C++开发,如果学过一点点数据结构课的话,肯定接触过排序这一块儿,什么快速排序、插入排序、冒泡排序的,然后大部分排序算法,步骤分解之后,最细节的操作都是两个数的相互比较,Chrome浏览器用的V8引擎就使用了快速排序。下面就贴一段当年学数据结构的时候快排的代码,V8的源码肯定不是这么简单,肯定是一种复杂的经过了各种优化(比如改善了稳定性,内存等)但基本的快排就是这样:左边右边一块儿往中间排,排出一个个有序的子段,然后再一个个子段中递归的排。
排序稳定性是指排序后数组中的相等值的相对位置没有改变,而不稳定性排序则会改变相等值的相对位置。
C++快速排序算法(这里是从小到大的正序算法):1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19void quick_sort(int left,int right){
if(left>right){
return;
}
int pivot=data[left],low=left,high=right;
while(low<high){
while(low<high && data[high]>=pivot){
high--;
}
data[low]=data[high];
while(low<high && data[low]<=pivot){
low++;
}
data[high]=data[low];
}
data[low]=pivot;
quick_sort(left,low-1);
quick_sort(low+1,right);
}
所以这样就清楚了,我们只要设置好了比较函数func(a,b)规定了每两个数排序的正逆序,就可以对整个数组进行快速排序,但要注意的是,因为快速排序是不稳定排序,所以sort方法也是不稳定的。
我们还可以令对象数组排序,这里是加强版排序,首先按last排序,然后按照first排序。
JS:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36var s=[
{first:"Tom",last:"cruse"},
{first:"Jack",last:"awddwa"},
{first:"Aommy",last:"rththr"},
{first:"Fuck",last:"ererg"},
{first:"Shit",last:"nbnb"},
{first:"Jessy",last:"awddwa"}
];
var by=function(name,minor){
return function(o,p){
var a,b;
if(typeof o==='object' && typeof p==='object' && o && p){
a=o[name];
b=p[name];
if(a===b){
//这里的minor(o,p)实际上是by('first')(o,p)
return typeof minor === 'function' ? minor(o,p) : 0;
}
if(typeof a=== typeof b){
return a<b?-1:1;
}
return typeof a < typeof b ? -1 : 1;
}else{
throw{
name: 'Error',
message: 'Expected an object when sorting by '+name
};
}
};
};
//因为by函数使用了闭包,这里的带两个参数的比较函数实际上是by(name)函数,即func(o,p)=by(name)(o,p)
//一个函数当参数的时候只写函数名即可,所以写成sort(by('last'))就行
s.sort(by("last",by("first")));
for(var i in s){
console.log(s[i].first+" "+s[i].last);
}
更多关于sort()的内容,请见MDN文档