成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

JS 中 Array.sort 的那些事兒

Sike / 3397人閱讀

摘要:然而有時(shí)候的結(jié)果和預(yù)期結(jié)果還是有些差異的。中文的可以通過來獲取。啊次比例中毓比侊啊比侊比例次毓中當(dāng)然和允許傳入?yún)?shù)指定,有興趣的可以去上看看用法。對(duì)于中文或者需要本地化比較的場(chǎng)景下,可以使用或者來進(jìn)行比較。

大家都知道 js 自帶了一個(gè)排序方法 sort,很多時(shí)候需要排序的時(shí)候也都直接使用了 sort 方法來排序。然而有時(shí)候 sort 的結(jié)果和預(yù)期結(jié)果還是有些差異的。

看下面的代碼

[1, 23, 2, 3].sort()

自然語言情況下,我們期望的 排序結(jié)果應(yīng)該是 [1,2,3,23] ,然而實(shí)際結(jié)果 [1, 2, 23, 3] 。

首先我們來看下各個(gè)瀏覽器( js 引擎) 的排序算法。

瀏覽器 使用的 JavaScript 引擎 排序算法 源碼地址
Google Chrome V8 插入排序和快速排序 sort 源碼實(shí)現(xiàn)
Mozilla Firefox SpiderMonkey 歸并排序 sort 源碼實(shí)現(xiàn)
Safari Nitro(JavaScriptCore ) 歸并排序和桶排序 sort 源碼實(shí)現(xiàn)
Microsoft Edge 和 IE(9+) Chakra 快速排序 sort 源碼實(shí)現(xiàn)
注:上述表格數(shù)據(jù)來源于 排序算法

v8 為例, 它分別使用了 插入排序和 快速排序,分別使用的場(chǎng)景 可以查看源碼,也可以看 justjavac 大佬的這篇文章 ,同時(shí)這篇文章也分析了一個(gè)排序的坑。

當(dāng) sort 沒傳遞 compareFn 的時(shí)候,就會(huì)使用默認(rèn)的 compareFn ,而 sort 很多的坑都源于這里。 根據(jù) justjavac 大大的那篇文章里的分析和 ecma 標(biāo)準(zhǔn)里的聲明,我們得知compareFn 會(huì)在內(nèi)部嘗試調(diào)用 toString 將比較的對(duì)象轉(zhuǎn)化成字符串。

在轉(zhuǎn)化成字符串這一步之后,坑就出現(xiàn)了。當(dāng) xy (這里 x、 y 都已經(jīng)是字符串了)進(jìn)行比較的,其實(shí)是依據(jù)字典序來比較的,而比較的對(duì)象其實(shí)數(shù)據(jù)的 charCode

字典序的比較方法引用一下 維基百科上的說法:

是先按照第一個(gè)字母、以 a、b、c……z 的順序排列;如果第一個(gè)字母一樣,那么比較第二個(gè)、第三個(gè)乃至后面的字母。如果比到最后兩個(gè)單詞不一樣長(zhǎng)(比如,sigh 和 sight),那么把短者排在前。

因此,在 [1, 23, 2, 3].sort() 中,比較的時(shí)候其實(shí)是 "1"、"23"、"2"、"3"、 來進(jìn)行比較的(注意引號(hào),是字符串)。 下面是這些字符串的 charCode 表:

1 23 2 3
49 50 51 50 51

"1""23" 比較,先比較第一位 charCode, 49 小于50,直接判定成功,"1"<"23" ,而 "23""2" 比較,第一位 charCode 相同,判斷不了,看第二位; 而第二位上 一個(gè)是 51,一個(gè)是”空“ 的,因此 2 < 23。而"23""3" 比較, 由于2charCode 小于 3 的, 因此也直接判定成功,23 < 3。

類比可以考慮一下我們小學(xué)時(shí)候使用的字典 ,字典前面的拼音索引, ai 的拼音也始終在 ba 前面,因?yàn)?a 的字典序小于 b 。

同樣的,來看下英文: ["a","ba","b","c","ca"]

a b ba c ca
97 98 98 97 99 97

根據(jù)上面的規(guī)則,我們可以很容易推斷出排序結(jié)果: ["a", "b", "ba", "c", "ca"]

最后看看中文的: ["啊","次","比例","中","毓","比侊"]

比例 比侊
21834 27425 27604 20363 20013 27603 27604 20362

同樣的,根據(jù)上面的規(guī)則,結(jié)果也是一目了然:["中", "啊", "次", "毓", "比侊", "比例"]

中文的 charCode可以通過 charCodeAt 來獲取。

這樣的排序結(jié)果很多時(shí)候并不是我們需要的,因此 sort 也允許我們傳入一個(gè) compareFn 來實(shí)現(xiàn)自定義排序規(guī)則,通過返回 -1、0、1 來覺得排序結(jié)果的大小順序。對(duì)于可以比較的數(shù)值,我們可以通過 x-y 的方式來處理,那么中文又該怎么辦呢?能不能按照拼音的順序來排序?

答案是肯定的!

String 現(xiàn)在有了一個(gè) localeCompare 的方法用于本地化比較。

["啊","次","比例","中","毓","比侊"].sort((x,y) => x.localeCompare(y))
// ["啊", "比侊", "比例", "次", "毓", "中"]

在 MDN 中,在涉及到大量比較的時(shí)候更推薦的是 Intl.Collator。 Intl 對(duì)象是 ECMAScript 國際化 API 的一個(gè)命名空間,它提供了精確的字符串對(duì)比,數(shù)字格式化,日期和時(shí)間格式化。

const collator = new Intl.Collator()
["啊","次","比例","中","毓","比侊"].sort(collator.compare)
// ["啊", "比侊", "比例", "次", "毓", "中"]

當(dāng)然 localeCompareIntl.Collator 允許傳入?yún)?shù)指定 locale, 有興趣的可以去 MDN 上看看用法。

最后,內(nèi)置 sort 的默認(rèn) compareFn 方法是基于字典序排序的, 而字典序比較的對(duì)象是 數(shù)據(jù)的 charCode。當(dāng) sort 默認(rèn)的排序行為和預(yù)期不一樣或者無法滿足需求的時(shí)候,我們可以傳入自定義的 compareFn 來進(jìn)行排序。對(duì)于中文或者需要本地化比較的場(chǎng)景下,可以使用 String.localeCompare 或者 Intl.Collator 來進(jìn)行比較。

最后的最后,如有錯(cuò)誤,歡迎大家指出,一起討論進(jìn)步。

文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請(qǐng)注明本文地址:http://systransis.cn/yun/108624.html

相關(guān)文章

  • JavaScript30秒, 從入門到放棄之Array(四)

    摘要:使用把指定運(yùn)算結(jié)果為的數(shù)組元素添加到二維數(shù)組的第一個(gè)數(shù)組中,運(yùn)算結(jié)果為的數(shù)組元素添加到二維數(shù)組的第二個(gè)數(shù)組中。所以改成了,它是不改變數(shù)組元素的,沒有副作用,不干擾后續(xù)。方法將剩余的所有數(shù)組元素以的方式返回結(jié)果數(shù)組。 原文地址:JavaScript30秒, 從入門到放棄之Array(四)博客地址:JavaScript30秒, 從入門到放棄之Array(四) 水平有限,歡迎批評(píng)指正 ma...

    wuaiqiu 評(píng)論0 收藏0
  • JS專題之?dāng)?shù)組去重

    摘要:將元素作為對(duì)象的鍵,默認(rèn)鍵對(duì)應(yīng)的值為如果對(duì)象中沒有這個(gè)鍵,則將這個(gè)元素放入結(jié)果數(shù)組中去。 前言 數(shù)組去重在日常開發(fā)中的使用頻率還是較高的,也是網(wǎng)上隨便一抓一大把的話題,所以,我寫這篇文章目的在于歸納和總結(jié),既然很多人都在提的數(shù)組去重,自己到底了解多少呢。又或者是如果自己在開發(fā)中遇到了去重的需求,自己能想到更好的解決方案嗎。 這次我們來理一理怎么做數(shù)組去重才能做得最合適,既要考慮兼容性,...

    only_do 評(píng)論0 收藏0
  • [聊一聊系列]聊一聊前端模板與渲染那些事兒

    摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...

    UCloud 評(píng)論0 收藏0
  • [聊一聊系列]聊一聊前端模板與渲染那些事兒

    摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...

    Yangder 評(píng)論0 收藏0
  • [聊一聊系列]聊一聊前端模板與渲染那些事兒

    摘要:歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面不僅僅是代碼作為現(xiàn)代應(yīng)用,的大量使用,使得前端工程師們?nèi)粘5拈_發(fā)少不了拼裝模板,渲染模板。我們今天就來聊聊,拼裝與渲染模板的那些事兒。一改俱改,一板兩用。 歡迎大家收看聊一聊系列,這一套系列文章,可以幫助前端工程師們了解前端的方方面面(不僅僅是代碼):https://segmentfault.com/blog...

    褰辯話 評(píng)論0 收藏0

發(fā)表評(píng)論

0條評(píng)論

最新活動(dòng)
閱讀需要支付1元查看
<