http://www.f-z.cn/id/212
在实际的业务当中,很多时候要对定义好的数组重新排序。在JavaScript中自带了两个方法,可以对数组进行排序操作。这两个方法就是sort()和reverse()。今天就来学习这两个方法相关的知识。
sort()方法对数组的元素做原地的排序,并返回这个数组。默认情况下,sort()方法是按升序排列数组项。即最小的值位于最前面,最大的值排列在最后面。为了实现排序,sort()方法会调用每个数组项的toString()转型方法,然后比较得到的字符串,以确定如何排序。
var arr = ['hello','jame','Jack','dog'];
console.log(arr.sort());
正如前面所言,sort()方法未调用任何参数时,是按升序排列的,也就是按字母的顺序排列,所以我们看到结果也是正确的。
var arr = [1,5,10,22];
console.log(arr.sort());
可见,即使示例中数组的顺序没有任何问题,但sort()方法对数组进行重新排序操作之后,顺序反而不对了。这究竟是为何呢?
查了相关文档才知道,sort()方法:如果省略参数,数组项会先根据toString()函数将其值转换成字符串在进行比较,是按UNICODE进行比较的,然后根据这个进行排序。正如最前面的示例,"Jack"会排在"dog"前面。当数字进行排序的时候,"5"会出现在"10"和"22"之后,因为他们先会被转换为字符串,而“10”和“22”都比“5”要靠前。
"Jack".charCodeAt() ==> 74
"dog".charCodeAt() ==> 100
"5".charCodeAt() ==> 53
"10".charCodeAt() ==> 49
"22".charCodeAt() ==> 50
如此一来,这不是最佳方案。幸好,sort()方法可以接受一个比较函数compareFunction作为参数,以便我们指定哪个值位于哪个值的前面。
如果指明了compareFunction,那么数组会按照调用该函数的返回值进行排序。比较函数compareFunction接收两个参数a和b,a和b是两个将要被比较的元素:
compareFunction(a,b)返回的值小于0:那么a就小于b,也就是说a排在了b的前面
compareFunction(a,b)返回的值大于0: 那么a就大于b,也就是说a排在了b的后面
compareFunction(a,b)返回的值等于0:那么a就等于b,也就是说a和b的位置保持不变
function compareFunction (a, b) {
if (a < b) {
return -1;
} else if (a > b) {
return 1;
} else {
return 0;
}
}
这个函数可适用于大多数数据类型,只要将compareFunction(a,b)函数作为参数传给sort()方法即可。因到前面的示例:
var arr = [1,5,10,22];
arr.sort(compareFunction);
console.log(arr);
数组arr仍然保持了正确的升序排列。其实可以通过compareFunction(a,b)对数组作降序排列,只需要将compareFunction函数的返回值做个调整即可:
function compareFunction (a, b){
if (a < b) {
return 1;
} else if (a > b) {
return -1;
} else {
return 0;
}
}
var arr = [1, 5, 10, 22];
arr.sort(compareFunction);
console.log(arr);
注:compareFunction(a, b) 必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。
上面也说到了,sort()方法传入compareFunction(a,b)参数时,返回的值可能有3个,所以下面这样的写法是错误的:
function compareFunction (a, b) {
return a < b;
}
var arr = [21, 0, 3, 11, 4, 5, 6, 7, 8, 9, 10];
arr.sort(compareFunction);
console.log(arr);
可能得的结果是 [5, 21, 11, 10, 9, 8, 7, 6, 4, 3, 0],这并不是正确的结果,那是因为return a < b只返回了两种值 true或false,相当于1或0,而没有-1。
对于数字类型或valueOf()方法返回数值类型的对象类型,可以使用一个更简单的比较函数。
function ascSort (a, b) {
return a - b;
}
function desSort (a, b) {
return b - a;
}
var arr = [1,4,10,3],
arr2 = [100,12,99,3,2];
arr.sort(ascSort);
arr2.sort(desSort);
console.log(arr);
console.log(arr2);
创建一个字符串数组,并且使用sort()对字符串进行重新排序:
var stringArray = ['blue', 'Humpback', 'Beluga'];
stringArray.sort();
console.log('字符串数组stringArray:' + stringArray);
字符串数组stringArray:Beluga,Humpback,blue
创建一个数字字符串数组之后对数组进行排序,对比数字数组分别指定与不指定比较函数的结果:
var numericStringArray = ['80', '9', '700'];
function compareFunction (a, b) {
return a - b;
}
console.log('不指定比较函数的数字字符串数组排列:' + numericStringArray.sort());
console.log('指定比较函数的数字字符串数组排列:' + numericStringArray.sort(compareFunction));
不指定比较函数的数字字符串数组排列:700,80,9
指定比较函数的数字字符串数组排列:9,80,700
创建一个数字数组之后对数组进行排序,对比数字数组分别指定与不指定比较函数的结果:
var numberArray = [80, 9, 700];
function compareFunction (a, b) {
return a - b;
}
console.log('不指定比较函数的数字数组排列:' + numberArray.sort());
console.log('指定比较函数的数字数组排列:' + numberArray.sort(compareFunction));
不指定比较函数的数字字符串数组排列:700,80,9
指定比较函数的数字字符串数组排列:9,80,700
创建一个数字和数字字符串混合数组之后进行排序,对比数组分别指定与不指定比较函数的结果:
var mixedNumericArray = ['80', '9', '700', 40, 1, 5, 200];
function compareFunction (a, b){
return a - b;
}
console.log('不指定比较函数的数组排列:' + mixedNumericArray.sort());
console.log('指定比较函数的数组排列' + mixedNumericArray.sort(compareFunction));
不指定比较函数的数组排列:1,200,40,5,700,80,9
指定比较函数的数组排列1,5,9,40,80,200,700
除了给数字数组进行升序或降序排列之外,还可以定义一个随机函数,实现数组的随机排列。定义的随机函数返回正数或者负数,并表将随机函数传给sort()方法,此时sort()方法根据随机函数返回的正负数来决定两个值之前的位置。
var randomArray = [9,0,23,8,3,5];
function randomSort(a, b) {
return Math.random() - 0.5;
}
console.log(randomArray.sort(randomSort));
function objectSort(property, desc) {
if (desc) {
return function (a, b) {
return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
}
}
return function (a, b) {
return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
}
}
var myArray = [
{ "name": "John Doe", "age": 29 },
{ "name": "Anna Smith", "age": 24 },
{ "name": "Peter Jones", "age": 39 }
]
console.log(myArray.sort(objectSort('name',true)));
另外,只需要改变比较函数objectSort()中的desc参数值为flase,数组就会按object指定的property属性降序排列:
console.log(myArray.sort(objectSort('age',false)));
function dynamicSort(property) {
var sortOrder = 1;
if(property[0] === "-") {
sortOrder = -1;
property = property.substr(1);
}
return function (a,b) {
var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
return result * sortOrder;
}
}
console.log(myArray.sort(dynamicSort('age')));
console.log(myArray.sort(dynamicSort('-age')));
上面介绍的是按一个属性进行排序,但很多时候,希望按多个属性排序,那么比较函数需要做一定的调整:
function dynamicSortMultiple() {
var props = arguments;
return function (obj1, obj2) {
var i = 0, result = 0, numberOfProperties = props.length;
while(result === 0 && i < numberOfProperties) {
result = dynamicSort(props[i])(obj1, obj2);
i++;
}
return result;
}
}
myArray.sort(dynamicSortMultiple('name','-age'));
reverse()方法相对而言要简单得多,它就是用来颠倒数组中元素的位置,并返回该数组的引用。比如我们有一个数组:
var myArray = ["Airen","W3cplus","Blog"];
console.log(myArray.reverse());
本文主要介绍了数组中元素项的排序方法。而主要详细介绍的是sort()方法。通过给sort()方法传递不同的比较函数,我们可以实现字符串数组、数字数组、数字和数字字符串混合数组、对象数组等按顺序(升序或降序)排列。
学习更多IT知识 加群:272292492