我们会经常遇到对数据进行排序的情况,如果好好讲一下排序就会讲到一大堆算法之类的比如:冒泡排序,堆排序,快速排序等等。这里我们仅用简单的js原生排序方法sort来实现一般数据的排序。
这里先介绍一下sort:
sort()
方法用原地算法对数组的元素进行排序,并返回数组。排序算法现在是稳定的。默认排序顺序是根据字符串Unicode码点。由于它取决于具体实现,因此无法保证排序的时间和空间复杂性。
例如,如果我们直接将一个数组进行排序,sort不会根据里面数字大小尽心排序,而是根据每项的unicode字符的顺序进行排序:
var months = ['March', 'Jan', 'Feb', 'Dec'];
months.sort();
console.log(months);
// expected output: Array ["Dec", "Feb", "Jan", "March"]
var array1 = [1, 30, 4, 21, 100000];
array1.sort();
console.log(array1);
// expected output: Array [1, 100000, 21, 30, 4]
上面第一个数组很好理解,因为字母顺序的unicode码递增。第二个数组中,结果出现1,10000,21。10000排在了21前面,这里就是根据字符顺序依次进行unicode码比较。入1和10000第一个字符1都相同,然后比较第二位,1没有第二位,10000又第二位0所以10000在1之后,而21的第一位直接是2比1大,所以在10000后面,不再比较后面的字符。
语法:arr.sort([compareFunction])
参数:compareFunction
| 可选
用来指定按某种顺序进行排列的函数。如果省略,元素按照转换为的字符串的各个字符的Unicode位点进行排序。
firstEl
第一个用于比较的元素。secondEl
第二个用于比较的元素。
返回值:排序后的数组。请注意,数组已原地排序,并且不进行复制。
如果没有指明 compareFunction
,那么元素会按照转换为的字符串的诸个字符的Unicode位点进行排序。例如 "Banana" 会被排列到 "cherry" 之前。当数字按由小到大排序时,9 出现在 80 之前,但因为(没有指明 compareFunction
),比较的数字会先被转换为字符串,所以在Unicode顺序上 "80" 要比 "9" 要靠前。
如果指明了 compareFunction
,那么数组会按照调用该函数的返回值排序。即 a 和 b 是两个将要被比较的元素:
compareFunction(a, b)
小于 0 ,那么 a 会被排列到 b 之前;compareFunction(a, b)
等于 0 , a 和 b 的相对位置不变。备注: ECMAScript 标准并不保证这一行为,而且也不是所有浏览器都会遵守(例如 Mozilla 在 2003 年之前的版本);compareFunction(a, b)
大于 0 , b 会被排列到 a 之前。compareFunction(a, b)
必须总是对相同的输入返回相同的比较结果,否则排序的结果将是不确定的。所以,比较函数格式如下:
function compare(a, b) {
if (a < b ) { // 按某种排序标准进行比较, a 小于 b
return -1;
}
if (a > b ) {
return 1;
}
// a must be equal to b
return 0;
}
要比较数字而非字符串,比较函数可以简单的以 a 减 b,如下的函数将会将数组升序排列
function compareNumbers(a, b) {
return a - b;
}
sort
方法可以使用函数表达式方便地书写:
var numbers = [4, 2, 5, 1, 3];
numbers.sort(function(a, b) {
return a - b;
});
console.log(numbers);
也可以写成:
var numbers = [4, 2, 5, 1, 3];
numbers.sort((a, b) => a - b);
console.log(numbers);
// [1, 2, 3, 4, 5]
对象可以按照某个属性排序:
var items = [
{ name: 'Edward', value: 21 },
{ name: 'Sharpe', value: 37 },
{ name: 'And', value: 45 },
{ name: 'The', value: -12 },
{ name: 'Magnetic' },
{ name: 'Zeros', value: 37 }
];
// sort by value
items.sort(function (a, b) {
return (a.value - b.value)
});
// sort by name
items.sort(function(a, b) {
var nameA = a.name.toUpperCase(); // ignore upper and lowercase
var nameB = b.name.toUpperCase(); // ignore upper and lowercase
if (nameA < nameB) {
return -1;
}
if (nameA > nameB) {
return 1;
}
// names must be equal
return 0;
});
referenceStr.localeCompare(compareString[, locales[, options]])
当排序非 ASCII 字符的字符串(如包含类似 e, é, è, a, ä 等字符的字符串)。一些非英语语言的字符串需要使用String.localeCompare
。这个函数可以将函数排序到正确的顺序。localeCompare()
方法返回一个数字来指示一个参考字符串是否在排序顺序前面或之后或与给定字符串相同。
返回值:如果引用字符存在于比较字符之前则为负数; 如果引用字符存在于比较字符之后则为正数;相等的时候返回 0 。这与sort中的函数两个值比较相似。
返回一个数字表示是否 引用字符串 在排序中位于 比较字符串 的前面,后面,或者二者相同。
切勿依赖于 -1 或 1 这样特定的返回值。不同浏览器之间(以及不同浏览器版本之间) 返回的正负数的值各有不同,因为W3C规范中只要求返回值是正值和负值,而没有规定具体的值。一些浏览器可能返回-2或2或其他一些负的、正的值。
示例:
var items = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];
items.sort(function (a, b) {
return a.localeCompare(b);
});
// items is ['adieu', 'café', 'cliché', 'communiqué', 'premier', 'réservé']
通过以上的介绍我们可以通过使用sort()和localeCompare()来实现一个简单的对数字、中英文等都能排序的方法:
//对数据进行排序
_sortData = (dataList,sortType,field)=>{
//拷贝一份数据
dataList = dataList.slice(0);
//判断是否含有非数字
let isNumber = dataList.some(item=>{
return isNaN(field ? item[field] : item);
});
if(sortType === 'asc'){
//升序
if(!isNumber){
//数字排序
dataList.sort((dataA,dataB)=>{
return (field
? +dataA[field] - +dataB[field]
: +dataA - +dataB);
});
}else{
//非数字排序
dataList.sort((dataA,dataB)=>{
return (field
? dataA[field].localeCompare(dataB[File])
: dataA.localeCompare(dataB));
})
}
}else if(sortType === 'desc'){
//降序
//升序
if(!isNumber){
//数字排序
dataList.sort((dataA,dataB)=>{
return (field
? +dataB[field] - +dataA[field]
: +dataB - +dataA);
});
}else{
//非数字排序
dataList.sort((dataA,dataB)=>{
return (field
? dataB[field].localeCompare(dataA[File])
: dataB.localeCompare(dataA));
})
}
}
return dataList;
}