javascript學習筆記(11)--sort排序

排序是在程序中經常用到的算法
無論使用冒泡排序還是快速排序,排序的核心是比較兩個元素的大小
通常規定,對於兩個元素x和y,如果認爲x < y,則返回-1,如果認爲x == y,則返回0,如果認爲x > y,則返回1

JavaScript的Array的sort()方法就是用於排序的
Array的sort()方法默認把所有元素先轉換爲String再排序,按照ASCII的大小,一位一位的進行比較,ASCII碼大的排在後面,如果比到某一位沒有了,那麼沒有的排在前面
這個原理還是挺好的,但在實際應用的時候會出現意料不到的結果

['Google', 'Apple', 'Microsoft'].sort();//Array(3) [ "Apple", "Google", "Microsoft" ]
['Google', 'apple', 'Microsoft'].sort();//Array(3) [ "Google", "Microsoft", "apple" ]
[10, 20, 1, 2].sort();//Array(4) [ 1, 10, 2, 20 ]

因爲小寫字母a的ASCII碼在大寫字母之後,所以第二個排序apple就排到了最後
第三個排序可能大家都難以想象,但這確實是按照上面的規則來的

 10>2
true
'10'>'2'
false

剛纔提到了,sort調用之前會把所有的array元素轉化爲字符串,然後字符串的比較原理剛纔也提到過…所以會造成…這麼奇怪的結果

如果不瞭解sort()方法的默認排序規則,直接對數字排序,絕對栽進坑裏

但sort()方法也是一個高階函數,它可以接收一個比較函數來實現自定義的排序
那麼這個比較函數要怎麼寫呢,其實又涉及到sort的原理
我在網上也找了很多資料,然後也自己測試了
發現firefox和node.js兩個原則不太一樣,而且差別很大…不試不知道,一試嚇一跳

在firefox裏面(記住sort會改變順序,所以測試的時候要重新定義a,不然可能a的順序改變了)

var a=[1,2,3,4]
a.sort(function (){return 1;})
Array(4) [ 4, 3, 2, 1 ]

a=[1,2,3,4];//Array(4) [ 1, 2, 3, 4 ]
a.sort(function (){return 3;})
Array(4) [ 4, 3, 2, 1 ]

a=[1,2,3,4];//Array(4) [ 1, 2, 3, 4 ]
a.sort(function (){return 0;})
Array(4) [ 1, 2, 3, 4 ]

a=[1,2,3,4];//Array(4) [ 1, 2, 3, 4 ]
a.sort(function (){return -1;})
Array(4) [ 1, 2, 3, 4 ]

a=[1,2,3,4];//Array(4) [ 1, 2, 3, 4 ]
a.sort(function (){return -3;})
Array(4) [ 1, 2, 3, 4 ]

可以發現sort()方法在接受到函數返回的1(準確的說是大於0的任意的數)時,就交換位置,如果接收到函數返回的-1(準確的說是小於0的任意數字)就保持順序不變,如果返回是0就認爲是一樣的順序,也保持不變

var a=[1,2,3,4]
a.sort(function(x,y){console.log(x,y);if(x<y)return -1;else if(x>y)return 1;else return 0;})
1 2 
2 3
3 4 
Array(4) [ 1, 2, 3, 4 ]

可以看出sort的原理,傳入的兩個參數,然後是依次比較相鄰的兩項,然後再看我們的算法
x<y,返回-1,就是不改變位置
x>y,返回1,就要交換位置
跟我們剛纔說的也是一致的
在這裏插入圖片描述而在node.js裏面,這個差別就大多了
首先是返回值的問題

 var a=[1,2,3,4]
> a.sort(function(){return 1;});//[ 1, 2, 3, 4 ]
> a=[1,2,3,4]
a.sort(function(){return 3;});//[ 1, 2, 3, 4 ] 
a=[1,2,3,4]  
 a.sort(function(){return 0;});//[ 1, 2, 3, 4 ]  
 a=[1,2,3,4]
 a.sort(function(){return -1;});//[ 4, 3, 2, 1 ] 
 a=[1,2,3,4]
 a.sort(function(){return -3;});//[ 4, 3, 2, 1 ]    

在node.js裏sort()方法在接受到函數返回的-1(準確的說是小於0的任意的數)時,就交換位置,如果接收到函數返回的1(準確的說是大於0的任意數字)就保持順序不變,如果返回是0就認爲是一樣的順序,也保持不變

var a=[1,2,3,4]
a.sort(function(x,y){console.log(x,y);if(x<y)return -1;else if(x>y)return 1;else return 0;})
 console.log(a);
 D:\Node\node.exe main.js 
2 1
3 2
4 3
[ 1, 2, 3, 4 ]

不知道怎麼想的,傳入的參數順序是反的,先是後面的那個,然後是前面的那個,雖然也是按着比較相鄰兩項
x<y,說明後面的小,就要返回-1交換位置
x>y說明後面大,就返回1不變
x=y,就返回0不變

不過怎麼說呢,這種設計的好處就是兼容性的問題,本來兩種算法是反的,但這麼一折騰,又可以通用了…

關於這點我也弄了挺長時間…百思不得其解,最後才發現有這麼大一個坑

所以以後遇到排序,就大膽寫就好了,兩種是等效的
從小往大

var arr = [10, 20, 1, 2]; 
arr.sort(function (x, y) {
 if (x < y) { return -1; }
 if (x > y) { return 1; }
 return 0; }); 

如果要從大到小排序,我們可以把大的數放前面:

var arr = [10, 20, 1, 2]; 
arr.sort(function (x, y) {
 if (x < y) { return 1; }
 if (x > y) { return -1; }
 return 0; }); 

但有時候我們需要忽略大小寫現,按照字母序排序

var arr = ['Google', 'apple', 'Microsoft']; 
 arr.sort(function (s1, s2) { 
 x1 = s1.toUpperCase(); 
 x2 = s2.toUpperCase(); //全部轉化爲大寫
 //字符串比較直接用<,>就可以
 if (x1 < x2) { return -1; }
 if (x1 > x2) { return 1; }
 return 0; });
 Array(3) [ "apple", "Google", "Microsoft" ]

忽略大小寫來比較兩個字符串,實際上就是先把字符串都變成大寫(或者都變成小寫),再比較

最後友情提示,sort()方法會直接對Array進行修改,sort之後Array值就被修改了

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章