數(shù)組的sort()和reverse()方法

在實(shí)際的業(yè)務(wù)當(dāng)中濒蒋,很多時(shí)候要對(duì)定義好的數(shù)組重新排序嗤练。在JavaScript中自帶了兩個(gè)方法,可以對(duì)數(shù)組進(jìn)行排序操作矿咕。這兩個(gè)方法就是sort()reverse()抢肛。今天就來學(xué)習(xí)這兩個(gè)方法相關(guān)的知識(shí)。

sort()方法

sort()方法對(duì)數(shù)組的元素做原地的排序碳柱,并返回這個(gè)數(shù)組捡絮。默認(rèn)情況下,sort()方法是按升序排列數(shù)組項(xiàng)莲镣。即最小的值位于最前面锦援,最大的值排列在最后面。為了實(shí)現(xiàn)排序剥悟,sort()方法會(huì)調(diào)用每個(gè)數(shù)組項(xiàng)的toString()轉(zhuǎn)型方法灵寺,然后比較得到的字符串,以確定如何排序区岗。

先來看一個(gè)簡(jiǎn)單的示例:

var arr = ['hello','jame','Jack','dog']; // 定義一個(gè)數(shù)組
console.log(arr.sort()); // ["Jack", "dog", "hello", "jame"]

正如前面所言略板,sort()方法未調(diào)用任何參數(shù)時(shí),是按升序排列的慈缔,也就是按字母的順序排列叮称,所以我們看到結(jié)果也是正確的。

接下來藐鹤,再看一個(gè)數(shù)字的數(shù)組排列的示例:

var arr = [1,5,10,22]; // 定義一個(gè)數(shù)組
console.log(arr.sort()); // [1, 10, 22, 5]

可見瓤檐,即使示例中數(shù)組的順序沒有任何問題,但sort()方法對(duì)數(shù)組進(jìn)行重新排序操作之后娱节,順序反而不對(duì)了挠蛉。這究竟是為何呢?

查了相關(guān)文檔才知道肄满,sort()方法:如果省略參數(shù)谴古,數(shù)組項(xiàng)會(huì)先根據(jù)toString()函數(shù)將其值轉(zhuǎn)換成字符串在進(jìn)行比較质涛,是按UNICODE進(jìn)行比較的,然后根據(jù)這個(gè)進(jìn)行排序掰担。正如最前面的示例汇陆,"Jack"會(huì)排在"dog"前面。當(dāng)數(shù)字進(jìn)行排序的時(shí)候带饱,"5"會(huì)出現(xiàn)在"10"和"22"之后毡代,因?yàn)樗麄兿葧?huì)被轉(zhuǎn)換為字符串,而“10”和“22”都比“5”要靠前勺疼。

我們可以使用charCodeAt()來驗(yàn)證一下:

"Jack".charCodeAt() ==> 74
"dog".charCodeAt()  ==> 100
"5".charCodeAt()    ==> 53
"10".charCodeAt()   ==> 49
"22".charCodeAt()   ==> 50

如此一來月趟,這不是最佳方案。幸好恢口,sort()方法可以接受一個(gè)比較函數(shù)compareFunction作為參數(shù)孝宗,以便我們指定哪個(gè)值位于哪個(gè)值的前面。

如果指明了compareFunction耕肩,那么數(shù)組會(huì)按照調(diào)用該函數(shù)的返回值進(jìn)行排序因妇。比較函數(shù)compareFunction接收兩個(gè)參數(shù)abab是兩個(gè)將要被比較的元素:

  • compareFunction(a,b)返回的值小于0:那么a就小于b猿诸,也就是說a排在了b的前面
  • compareFunction(a,b)返回的值大于0: 那么a就大于b婚被,也就是說a排在了b的后面
  • compareFunction(a,b)返回的值等于0:那么a就等于b,也就是說ab的位置保持不變

compareFunction(a,b)函數(shù):

function compareFunction (a, b) {
    if (a < b) {
        return -1; // a排在b的前面
    } else if (a > b) {
        return 1; // a排在b的后面
    } else {
        return 0; // a和b的位置保持不變
    }
}

這個(gè)函數(shù)可適用于大多數(shù)數(shù)據(jù)類型梳虽,只要將compareFunction(a,b)函數(shù)作為參數(shù)傳給sort()方法即可址芯。因到前面的示例:

var arr = [1,5,10,22]; // 定義一個(gè)數(shù)組
arr.sort(compareFunction); // 將compareFunction函數(shù)作為參數(shù)傳給 sort()
console.log(arr); // [1, 5, 10, 22]

數(shù)組arr仍然保持了正確的升序排列。其實(shí)可以通過compareFunction(a,b)對(duì)數(shù)組作降序排列窜觉,只需要將compareFunction函數(shù)的返回值做個(gè)調(diào)整即可:

function compareFunction (a, b){
    if (a < b) {
        return 1; // a排在b的后面
    } else if (a > b) {
        return -1; // a排在b的前面
    } else {
        return 0; // a 和 b 保持位置不變
    }
}

var arr = [1, 5, 10, 22]; //定義一個(gè)數(shù)組
arr.sort(compareFunction); // 將compareFunction函數(shù)作為參數(shù)傳給sort()
console.log(arr); // [22, 10, 5, 1]

注:compareFunction(a, b) 必須總是對(duì)相同的輸入返回相同的比較結(jié)果谷炸,否則排序的結(jié)果將是不確定的。

上面也說到了禀挫,sort()方法傳入compareFunction(a,b)參數(shù)時(shí)旬陡,返回的值可能有3個(gè),所以下面這樣的寫法是錯(cuò)誤的:

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]

可能得的結(jié)果是 [5, 21, 11, 10, 9, 8, 7, 6, 4, 3, 0]语婴,這并不是正確的結(jié)果描孟,那是因?yàn)?code>return a < b只返回了兩種值 truefalse,相當(dāng)于10砰左,而沒有-1匿醒。

對(duì)于數(shù)字類型或valueOf()方法返回?cái)?shù)值類型的對(duì)象類型,可以使用一個(gè)更簡(jiǎn)單的比較函數(shù)缠导。

// ascSort(a,b)傳給sort()廉羔,數(shù)字?jǐn)?shù)組作升序排列
function ascSort (a, b) {  // a和b是數(shù)組中相鄰的兩個(gè)數(shù)組項(xiàng)
    return a - b; 
    // 如果 return -1, 表示a小于b,a排列在b的前面
    // 如果 return 1, 表示a大于b,a排列在b的后面
    // 如果 return 0, 表示a等于b,a和b的位置保持不變
}

// desSort(a,b)傳給sort()酬核,數(shù)字?jǐn)?shù)組作降序排列
function desSort (a, b) { // a和b是數(shù)組中相鄰的兩個(gè)數(shù)組項(xiàng)
    return b - a;
    // 如果 return -1, 表示b小于a蜜另,b排列在a的前面
    // 如果 return 1, 表示b大于a, b排列在a的后面
    // 如果 return 0, 表示 b等于a, b和a的位置保持不變
}

來看看結(jié)果是不是我們想要的結(jié)果:

var arr = [1,4,10,3], 
    arr2 = [100,12,99,3,2]; //定義數(shù)組
arr.sort(ascSort); // 將ascSort函數(shù)傳給sort()
arr2.sort(desSort); // 將desSort函數(shù)傳給sort()
console.log(arr); // [1, 3, 4, 10]
console.log(arr2); // [100, 99, 12, 3, 2]

字符數(shù)組排列

創(chuàng)建一個(gè)字符串?dāng)?shù)組,并且使用sort()對(duì)字符串進(jìn)行重新排序:

var stringArray = ['blue', 'Humpback', 'Beluga'];
stringArray.sort();
console.log('字符串?dāng)?shù)組stringArray:' + stringArray);

Chrome輸出的結(jié)果:

字符串?dāng)?shù)組stringArray:Beluga,Humpback,blue

數(shù)字字符串?dāng)?shù)組排列

創(chuàng)建一個(gè)數(shù)字字符串?dāng)?shù)組之后對(duì)數(shù)組進(jìn)行排序嫡意,對(duì)比數(shù)字?jǐn)?shù)組分別指定與不指定比較函數(shù)的結(jié)果:

var numericStringArray = ['80', '9', '700'];

function compareFunction (a, b) {
    return a - b;
}

console.log('不指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:' + numericStringArray.sort());
console.log('指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:' + numericStringArray.sort(compareFunction));

Chrome輸出的結(jié)果:

不指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:700,80,9
指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:9,80,700

數(shù)字?jǐn)?shù)組排列

創(chuàng)建一個(gè)數(shù)字?jǐn)?shù)組之后對(duì)數(shù)組進(jìn)行排序举瑰,對(duì)比數(shù)字?jǐn)?shù)組分別指定與不指定比較函數(shù)的結(jié)果:

var numberArray = [80, 9, 700];

function compareFunction (a, b) {
    return a - b;
}

console.log('不指定比較函數(shù)的數(shù)字?jǐn)?shù)組排列:' + numberArray.sort());
console.log('指定比較函數(shù)的數(shù)字?jǐn)?shù)組排列:' + numberArray.sort(compareFunction));

Chrome輸出的結(jié)果:

不指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:700,80,9
指定比較函數(shù)的數(shù)字字符串?dāng)?shù)組排列:9,80,700

數(shù)字和數(shù)字字符串混合數(shù)組排列

創(chuàng)建一個(gè)數(shù)字和數(shù)字字符串混合數(shù)組之后進(jìn)行排序,對(duì)比數(shù)組分別指定與不指定比較函數(shù)的結(jié)果:

var mixedNumericArray = ['80', '9', '700', 40, 1, 5, 200];

function compareFunction (a, b){
    return a - b;
}

console.log('不指定比較函數(shù)的數(shù)組排列:' + mixedNumericArray.sort());
console.log('指定比較函數(shù)的數(shù)組排列' + mixedNumericArray.sort(compareFunction));

Chrome輸出的結(jié)果:

不指定比較函數(shù)的數(shù)組排列:1,200,40,5,700,80,9
指定比較函數(shù)的數(shù)組排列1,5,9,40,80,200,700

數(shù)字?jǐn)?shù)組隨機(jī)排列

除了給數(shù)字?jǐn)?shù)組進(jìn)行升序或降序排列之外蔬螟,還可以定義一個(gè)隨機(jī)函數(shù)此迅,實(shí)現(xiàn)數(shù)組的隨機(jī)排列。定義的隨機(jī)函數(shù)返回正數(shù)或者負(fù)數(shù)旧巾,并表將隨機(jī)函數(shù)傳給sort()方法耸序,此時(shí)sort()方法根據(jù)隨機(jī)函數(shù)返回的正負(fù)數(shù)來決定兩個(gè)值之前的位置。

var randomArray = [9,0,23,8,3,5];

function randomSort(a, b) {
    return Math.random() - 0.5;
}

console.log(randomArray.sort(randomSort));
// [8, 5, 9, 0, 23, 3]
// [8, 3, 5, 0, 23, 9]
// [8, 5, 0, 3, 9, 23]

對(duì)象數(shù)組排列

對(duì)于對(duì)象數(shù)組排列鲁猩,我們同樣需要先寫一個(gè)構(gòu)造函數(shù):

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))); // 按object中的name的降序排列

來看看Chrome輸出的前后結(jié)果:

數(shù)組中Object排序

另外坎怪,只需要改變比較函數(shù)objectSort()中的desc參數(shù)值為flase,數(shù)組就會(huì)按object指定的property屬性降序排列:

console.log(myArray.sort(objectSort('age',false))); //按objcet中的age升序排列

Chrome輸出的前后結(jié)果:

數(shù)組中Object排序

除此之外廓握,還有其的對(duì)比較函數(shù)搅窿,如下所示:

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'))); // 按降序排列

上面介紹的是按一個(gè)屬性進(jìn)行排序,但很多時(shí)候隙券,希望按多個(gè)屬性排序男应,那么比較函數(shù)需要做一定的調(diào)整:

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()方法

reverse()方法相對(duì)而言要簡(jiǎn)單得多,它就是用來顛倒數(shù)組中元素的位置娱仔,并返回該數(shù)組的引用沐飘。比如我們有一個(gè)數(shù)組:

var myArray = ["Airen","W3cplus","Blog"];
console.log(myArray.reverse()); // ["Blog", "W3cplus", "Airen"]

總結(jié)

本文主要介紹了數(shù)組中元素項(xiàng)的排序方法。而主要詳細(xì)介紹的是sort()方法牲迫。通過給sort()方法傳遞不同的比較函數(shù)耐朴,我們可以實(shí)現(xiàn)字符串?dāng)?shù)組數(shù)字?jǐn)?shù)組盹憎、數(shù)字和數(shù)字字符串混合數(shù)組隔箍、對(duì)象數(shù)組等按順序(升序降序)排列。

初學(xué)者學(xué)習(xí)筆記脚乡,如有不對(duì)蜒滩,還希望高手指點(diǎn)。如有造成誤解奶稠,還希望多多諒解俯艰。

著作權(quán)歸作者所有。
商業(yè)轉(zhuǎn)載請(qǐng)聯(lián)系作者獲得授權(quán),非商業(yè)轉(zhuǎn)載請(qǐng)注明出處锌订。
原文: https://www.w3cplus.com/javascript/array-part-4.html ? w3cplus.com

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末竹握,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子辆飘,更是在濱河造成了極大的恐慌啦辐,老刑警劉巖谓传,帶你破解...
    沈念sama閱讀 219,188評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異芹关,居然都是意外死亡续挟,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,464評(píng)論 3 395
  • 文/潘曉璐 我一進(jìn)店門侥衬,熙熙樓的掌柜王于貴愁眉苦臉地迎上來诗祸,“玉大人,你說我怎么就攤上這事轴总≈甭” “怎么了?”我有些...
    開封第一講書人閱讀 165,562評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵怀樟,是天一觀的道長(zhǎng)功偿。 經(jīng)常有香客問我,道長(zhǎng)往堡,這世上最難降的妖魔是什么脖含? 我笑而不...
    開封第一講書人閱讀 58,893評(píng)論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮投蝉,結(jié)果婚禮上养葵,老公的妹妹穿的比我還像新娘。我一直安慰自己瘩缆,他們只是感情好关拒,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,917評(píng)論 6 392
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著庸娱,像睡著了一般着绊。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上熟尉,一...
    開封第一講書人閱讀 51,708評(píng)論 1 305
  • 那天归露,我揣著相機(jī)與錄音,去河邊找鬼斤儿。 笑死剧包,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的往果。 我是一名探鬼主播疆液,決...
    沈念sama閱讀 40,430評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼陕贮!你這毒婦竟也來了堕油?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 39,342評(píng)論 0 276
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎掉缺,沒想到半個(gè)月后卜录,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,801評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡眶明,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,976評(píng)論 3 337
  • 正文 我和宋清朗相戀三年艰毒,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片赘来。...
    茶點(diǎn)故事閱讀 40,115評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡现喳,死狀恐怖凯傲,靈堂內(nèi)的尸體忽然破棺而出犬辰,到底是詐尸還是另有隱情,我是刑警寧澤冰单,帶...
    沈念sama閱讀 35,804評(píng)論 5 346
  • 正文 年R本政府宣布幌缝,位于F島的核電站,受9級(jí)特大地震影響诫欠,放射性物質(zhì)發(fā)生泄漏涵卵。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,458評(píng)論 3 331
  • 文/蒙蒙 一荒叼、第九天 我趴在偏房一處隱蔽的房頂上張望轿偎。 院中可真熱鬧,春花似錦被廓、人聲如沸坏晦。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,008評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽昆婿。三九已至,卻和暖如春蜓斧,著一層夾襖步出監(jiān)牢的瞬間仓蛆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 33,135評(píng)論 1 272
  • 我被黑心中介騙來泰國(guó)打工挎春, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留看疙,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,365評(píng)論 3 373
  • 正文 我出身青樓直奋,卻偏偏與公主長(zhǎng)得像狼荞,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帮碰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,055評(píng)論 2 355