array.sort()方法及原理

sort()方法在適當的位置對數組進行排序,並且返回數組。

對於sort()方法,W3school給的定義是

arrayObject.sort(sortby)

說明

如果調用該方法時沒有使用參數,將按字母順序對數組中的元素進行排序,說得更精確點,是按照字符編碼的順序進行排序。要實現這一點,首先應把數組的元素都轉換成字符串(如有必要),以便進行比較。

如果想按照其他標準進行排序,就需要提供比較函數,該函數要比較兩個值,然後返回一個用於說明這兩個值的相對順序的數字。比較函數應該具有兩個參數 a 和 b,其返回值如下:

  • 若 a 小於 b,在排序後的數組中 a 應該出現在 b 之前,則返回一個小於 0 的值。
  • 若 a 等於 b,則返回 0。
  • 若 a 大於 b,則返回一個大於 0 的值。

arrayObject.sort(sortby):參數可選。規定排序順序。必須是函數。

可知參數是可選的,也就是有兩種情況,一是不加參數,另外一種是加函數參數,參數必須是函數。函數就是比較函數。

先看第一種不加參數的情況:

        var arr=[1,3,10,4,2];
        arr.sort();
        alert(arr);   //1,10,2,3,4

默認排序順序是升序,在上面的例子當中,我們感覺排序的結果是:1,2,3,4,10。怎麼出來10反而在前面呢?那是因爲sort()排序是按照字符串的Unicode碼,10的比後面的小,則他在前面,但是這個結果不是我們想要的,那怎麼辦?此時我們就要用到第二種情況:加函數參數。

第二種加函數參數的情況:

        var arr=[1,3,10,4,2];
        function compare(value1,value2) {
            if(value1<value2){return -1;}
            else if(value1>value2){return 1;}
            else {return 0}
        }
        arr.sort(compare);
        alert(arr)   //1,2,3,4,10

按照我的理解是,在對於一個數組使用sort()方法時,會逐項的將數組中的元素傳入到compare函數中作爲參數,也就是說在上面 var arr=[1,3,10,4,2]使用sort()方法時,按照順序先把1,3分別傳給value1和value2,再比較1和3的大小,顯然1<3,那麼根據判斷函數返回-1;sort()方法在接受到函數返回的-1時,就做出按照升序的原理不換位置,現在雖然數組位置沒有變,但是數組是刷新過一邊的,sort()返回了一個新的數組,所以在第二次傳入參數的時候,是傳入的第二項3和第三項10(第一次換位置的話,那麼第二項就是換過後的第二項)按着同樣的原理進行比較返回-1;後面的步驟就一樣了,在第三次比較的時候要注意,如果前面的返回值爲-1,那麼新數組的第一項和第二項不用再比較(升序,-1就不比較,因爲-1表示大數本來就在後面 ),如上面所示:1<3,3<10,那麼1<10;如果爲1,比如,2<5,5>1第二個返回值是1,則排完的新數是:2,1,5;所以接下來就是2和1比較,最終的1,2,5……所以上面的結果是1,2,3,4,10

接下來我用一個例子來說明這個過程:
 

      var arr=[1,3,10,4,2,5];
      function compare(value1,value2) {
            console.log(value1,value2,arr);
            if(value1<value2){return -1;}
            else if(value1>value2){return 1;}
            else {return 0}
        }
        arr.sort(compare);
        alert(arr);   //1,2,3,4,5,10

這段代碼在第三行加了console.log(value1,value2,arr);爲了更好理解參數傳入和比較的過程,下面圖是輸出結果,可能上面講的那段話,有的人覺得繁瑣,那麼接下來我用段代碼逐行分析。

(我本來是想在控制檯輸出數組,結果出現這種重複以及丟失的排序,目前還沒有解決,提出來讓大家知道,以下排序過程是對的,只是控制檯輸出有誤。)

我們定義的數組是這樣的 arr=[1,3,10,4,2,5]
第一行:傳入的是value1=1,value2=3,比較大小返回-1,數組的位置不變。
第二行:傳入的是value1=3,value2=10,比較大小返回-1,數組的位置不變。
第三行:傳入的是value1=10,value2=4,比較大小返回1,兩項交換位置,現在的數組是arr=[1,3,4,10,2,5]
第四行:現在不是繼續往後面比較,由於返回值爲1(這是升序,1的時候往前面比較),則在第三行操作交換位置後,這傳入的參數是value1=3,value2=4,比較大小,返回-1,位置不變,數組還是arr=[1,3,4,10,2,5]
第五行:這才繼續向後比較,傳入value1=10,value2=2,比較大小,返回1,交換位置,數組爲arr=[1,3,4,2,10,5]
第六行:前面的返回值又是1,則又比較前面的,value1=4,value2=2,比較大小,返回1,數組變爲arr=[1,3,2,4,10,5]
第七行:第六行結果返回值是1,所以這個地方也不能往後面比較,value1=3,value2=2;比較大小,返回1,數組爲arr=[1,2,3,4,10,5]
第八行:同理,value1=1,value2=2,比較大小返回-1,數組不變。
第九行:繼續往後面比較,value1=10,value2=5,比較大小,返回1,改變位置,數組是arr=[1,2,3,4,5,10]
最後一行:前面返回值是1,則向前比較,value1=4,value2=5,比較大小,返回-1,數組不變,(因爲前面4前面的數是排好序的,只要5>4,就會比前面都大,則前面不用比較。)

傳參的詳細過程就是這樣,所以最後得到的數組是:arr=[1,2,3,4,5,10],上面是谷歌測試。

這是火狐的,結果是一樣的,傳參是一樣的,但是控制檯輸出的數組沒有變過

這是IE的,IE給value1,value2傳值的順序和谷歌,火狐是相反的,並且它的控制檯不輸出arr數組,但是它的結果還是一樣的。

我又把上述代碼裏的數組改了:var arr=['a','C','b','D','d'];

再改成:var arr = ['réservé', 'premier', 'cliché', 'communiqué', 'café', 'adieu'];

谷歌這個結果是對的,但是控制檯在輸出步驟當中出了一點錯誤(我圈出來的重複出現,還有一個不在了,但是結果是對的,目前還沒有解決)

火狐的控制檯輸出數組沒變,但是結果是一樣的

IE的結果也是一樣的。
這個例子說明字符串也是可以用這個方法來排序的
《JavaScript高級程序設計》上面說,compare函數適合大多數數據類型。

 


————————————————
版權聲明:本文爲CSDN博主「erdaidai」的原創文章,遵循 CC 4.0 BY-SA 版權協議,轉載請附上原文出處鏈接及本聲明。
原文鏈接:https://blog.csdn.net/erdaidai/article/details/78054447

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