JavaScript陣列(一)——排序
JavaScript陣列中有一個reverse()
方法,可用於反轉陣列,如下程式碼所示:
var arr = [0, 1, 2, 3];
arr.reverse();
console.log(arr);//[3, 2, 1, 0]
但是多數情況下這並不能滿足開發的需求,真實的情況往往是降序或升序排列。對陣列進行排序很自然地會想到氣泡排序演算法,下面我們來看一個例子:
var arr = [8, 1, 35, 3, 10]; // 氣泡排序 升序 function bubbleSort(arr){ var temp; for(var i = 0; i < arr.length; i++){ for(var j = i + 1; j < arr.length; j++){ if(arr[i] > arr[j]){ temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } } return arr; } console.log(bubbleSort(arr));//[1, 3, 8, 10, 35]
這段程式碼有兩個for
迴圈,實現的思路是用外層迴圈依次取出每個元素,用內層迴圈和剩下的元素進行比較,如果取出的這個數較大,就與較小的數交換位置,這樣一輪內迴圈結束,最小的數就成了第一個元素,依次第二小的數成為第二個元素...。用下面這幅圖可以幫助理解:
如圖所示,i = 0
時,取出陣列的第一個元素,和之後的每個元素比較,如果大於後面的元素就交換位置,這樣當j
從1
到4
結束時,陣列的第一個元素就是最小的元素。相似的,i = 1
時,取出的是陣列的第二個元素,依次和後面的每個元素比較,當j
從2
到4
結束時,陣列的第二個元素就是第二小的元素。
從比較的過程也容易計算出比較的次數:
4 + 3 + 2 + 1 = n(n + 1) / 2 = (arr.length - 1)arr.length / 2 = 10
另一種思路是把相鄰的兩個元素進行比較,如果前者較大就交換二者的位置,這樣一輪內迴圈結束後,最大的元素就是陣列的最後一個元素,如下例所示:
function bubbleSort2(arr){
var temp;
for(var i = 0; i < arr.length - 1; i++){
for(var j = 0; j < arr.length - 1 - i; j++){
if(arr[j] > arr[j + 1]){
temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
}
}
}
return arr;
}
console.log(bubbleSort2(arr));//[1, 3, 8, 10, 35]
同樣畫一個圖來表示:
i = 0
時,j
從0
到3
迴圈,依次比較相鄰的兩個數,前者大就交換,這樣最大的數就像冒泡一樣冒到了最後;i = 1
時,第二大的數冒到了倒數第二的位置。
同樣也容易計算出比較的次數:
4 + 3 + 2 + 1 = n(n + 1) / 2 = (arr.length - 1)arr.length / 2 = 10
和第一種思路比較的次數是一樣的,只是從過程來看,第二種思路更名副其實一些。
其實對於這種常用的升降排序,JavaScript給我們提供了一個更方便的方法:sort()
。
在預設情況下,sort()
方法按升序排列陣列元素,為了實現排序,sort()
方法會呼叫每個元素的toString()
轉型方法,然後比較得到的字串,以確定如何排序。即使陣列的每個元素都是數值,sort()
方法比較的也是字串,如下所示:
arr.sort();
console.log(arr);//[1, 10, 3, 35, 8]
如結果所示,按照字串順序'10'
排在'1'
的後面,'3'
排在'10'
的後面,'8'
是最大的排在最後。顯然這並不是我們希望的結果,因此,sort()
方法可以接收一個比較函式作為引數,以便我們指定哪個值位於哪個值前面。看下面的示例:
function compare(v1, v2){
if(v1 < v2){
return -1;
}else if(v1 > v2){
return 1;
}else{
return 0;
}
}
arr.sort(compare);
console.log(arr);//[1, 3, 8, 10, 35]
如程式碼所示,宣告一個compare
比較函式,它接收兩個引數。compare
傳遞給sort
方法時,引數可以對映到陣列的元素,如果第一個引數應該位於第二個引數之前則返回一個負數,如果兩個引數相等則返回0
,如果第一個引數應該位於第二個引數之後則返回一個正數。這裡當v1 < v2
時返回-1
,也就是v1 < v2
時,v1
應該位於v2
之前,即升序。
當然如果想降序排列也很容易,只要改變返回值就好了,-1
改為1
,1
改為-1
,如下所示:
function compare(v1, v2){
if(v1 < v2){
return 1;
}else if(v1 > v2){
return -1;
}else{
return 0;
}
}
arr.sort(compare);
console.log(arr);//[35, 10, 8, 3, 1]
因為起關鍵作用的是返回值的正負與否,所以也可以使用下面這樣更簡化的方式:
//升序
function ascSort(v1, v2) {
return v1 - v2;
}
arr.sort(ascSort);
console.log(arr);//[1, 3, 8, 10, 35]
//降序
function descSort(v1, v2){
return v2 - v1;
}
arr.sort(descSort);
console.log(arr);//[35, 10, 8, 3, 1]
總結一句就是如果只是想反轉陣列,可以使用reverse()
方法,如果想對陣列進行升序或降序排列,可以使用s