需求的產(chǎn)生
今天在需求評(píng)審的過(guò)程中,遇見(jiàn)一個(gè)排序問(wèn)題
地區(qū)的拼音按照a-z的順序進(jìn)行排序。
研究了一下,主要有下面三種做法。
1,使用 String.prototype.localeCompare()
2,new Intl.Collator()
3,使用第3方庫(kù) pinyin
下面我們來(lái)詳細(xì)的介紹一下3種實(shí)現(xiàn)方法。
localeCompare 的介紹
localeCompare:用于比較兩個(gè)字符串,并返回一個(gè)數(shù)字,表示哪個(gè)字符串應(yīng)該排在前面。
語(yǔ)法:string.localeCompare(compareString, locales, options)
localeCompare 的第2個(gè)參數(shù)說(shuō)明:
默認(rèn)情況下,中文會(huì)按 Unicode 編碼排序。
添加 'zh-Hans-CN' 后自動(dòng)啟用拼音順序。
'zh-CN':zh-CN 是地區(qū)導(dǎo)向的標(biāo)簽(中國(guó)大陸中文)
'zh-Hans-CN': zh-Hans-CN 是腳本+地區(qū)導(dǎo)向的標(biāo)簽(中國(guó)大陸簡(jiǎn)體中文)
需要精確控制時(shí)選zh-Hans-CN,追求通用兼容時(shí)選zh-CN
localeCompare 的第3個(gè)參數(shù)options說(shuō)明:(可選):一個(gè)對(duì)象,指定比較的行為。
ignorePunctuation:true, 忽略標(biāo)點(diǎn)符號(hào)。
caseFirst:控制大小寫(xiě)排序順序。'upper':大寫(xiě)字母優(yōu)先, 'lower':小寫(xiě)字母優(yōu)先。
numeric:設(shè)為true時(shí),按數(shù)字順序比較字符串。如“蘋(píng)果10”排在“蘋(píng)果2”之后。
sensitivity :控制比較敏感度。有下面這些值
'base':僅比較基礎(chǔ)字符(忽略重音和大小寫(xiě))。
'case':考慮大小寫(xiě)差異。
localeCompare的排序原理:
string.localeCompare(compareString, 'zh-CN')
在中文環(huán)境下會(huì)使用拼音(聲母→韻母→聲調(diào))的字典順序進(jìn)行排序。
示例:'北方', 會(huì)排在 '北京' 的前面。
localeCompare實(shí)現(xiàn)排序
const arr = [
'南寧','阿壩州', '河池', '柳州',
'桂林','北安州', '賀州', '梧州','北院', '北京'
];
const newArr = arr.sort((a, b) => a.localeCompare(b, 'zh-Hans-CN'));
console.log(newArr, arr);

const nameArr = [
{"text": "北京", "value": "北京"},
{"text": "阿壩州", "value": "阿壩州"},
{"text": "桂林", "value": "桂林"},
{"text": "南寧", "value": "南寧"},
];
const newArr = nameArr.sort((a, b) => a.text.localeCompare(b.text, 'zh-Hans-CN'));
console.log(newArr, nameArr);

我們發(fā)現(xiàn)使用localeCompare確實(shí)可以按照拼音進(jìn)行排序啦。
有機(jī)智的小伙伴會(huì)說(shuō):如果瀏覽器不支持呢?
我查詢(xún)過(guò)資料,確實(shí)會(huì)有這樣的情況、
如:localeCompare函數(shù)在X5內(nèi)核(android版的微信瀏覽器)的瀏覽器不兼容該函數(shù),請(qǐng)注意使用。
我們可以先去檢查一下,是否支持排序,如果不支持就不進(jìn)行排序。
因?yàn)椋翰慌判蚩偙葓?bào)錯(cuò)要強(qiáng)上不少。

避免依賴(lài)localeCompare的返回值
ECMAScript 規(guī)范僅要求localeCompare返回正/負(fù)/零。
但是不同瀏覽器可能返回 -1、-2、1、2 等
檢查瀏覽器是否支持localeCompare排序
在使用 localeCompare 方法之前,先檢測(cè)瀏覽器是否支持 localeCompare 方法。
如果支持,則返回 true,否則返回 false。
function isPinYinSupported() {
try {
const testArr = ['北京', '上海','成都']
testArr.sort((a, b) => a.localeCompare(b, 'zh-Hans-CN'))
return true
} catch (e) {
return false
}
}
Intl.Collator 的介紹
Intl.Collator 用于根據(jù)語(yǔ)言環(huán)境對(duì)字符串進(jìn)行比較和排序。
是國(guó)際化(i18n)API 的核心組件。
語(yǔ)法:new Intl.Collator(locales, options)
locales: 指定區(qū)域設(shè)置,如'zh-CN'表示簡(jiǎn)體中文
options是一個(gè)對(duì)象,有下面這些值
-caseFirst:控制大小寫(xiě)排序順序,可選upper(大寫(xiě)優(yōu)先), lower(小寫(xiě)優(yōu)先)
-numeric:設(shè)為true時(shí),按數(shù)字順序比較字符串。如“蘋(píng)果10”排在“蘋(píng)果2”之后。
-ignorePunctuation:設(shè)為true時(shí)忽略標(biāo)點(diǎn)符號(hào),例 “你好,世界” 和 “你好世界” 會(huì)被視為相同
-sensitivity:控制比較的敏感度。
--它的值有:case(考慮大小寫(xiě)),base(僅比較基礎(chǔ)字符,忽略重音和大小寫(xiě))
排序時(shí),忽略標(biāo)點(diǎn)符號(hào)
const collatorIgnorePunct = new Intl.Collator('zh-CN', { ignorePunctuation: true });
console.log(collatorIgnorePunct.compare('你好,世界', '你好世界'));
排序時(shí),照數(shù)字排序
const arr = ['蘋(píng)果10', '蘋(píng)果14','蘋(píng)果2']
const collator = new Intl.Collator('zh-CN', { numeric: true });
const sortedArr = arr.sort((a,b)=> collator.compare(a,b));
console.log(sortedArr);

Intl.Collator 的排序 a-z進(jìn)行排序
const arr = [
'南寧','阿壩州', '河池', '柳州', '北方', '大連',
'桂林','北安州', '賀州', '梧州','北院', '北京'
];
const collator = new Intl.Collator('zh-CN');
const sortedArr = arr.sort((a,b)=> collator.compare(a,b));
console.log(sortedArr);

const arr = [
'南寧','阿壩州', '河池', '柳州', '北方', '大連',
'桂林','北安州', '賀州', '梧州','北院', '北京'
];
const collator = new Intl.Collator('zh-CN');
const sortedArr = arr.sort(collator.compare);
console.log(sortedArr);

Intl.Collator 的排序 z-a進(jìn)行排序
const arr = [
'南寧','阿壩州', '河池', '柳州', '北方', '大連',
'桂林','北安州', '賀州', '梧州','北院', '北京'
];
const collator = new Intl.Collator('zh-CN');
const sortedArr = arr.sort((a, b) => collator.compare(b, a));
console.log(sortedArr);

檢查瀏覽器是否支持 Intl.Collator
function supportIntlCollator(){
if (typeof Intl === 'undefined' || typeof Intl.Collator !== 'function') {
return false;
}
try {
new Intl.Collator('zh-CN');
return true;
} catch (e) {
return false;
}
}
console.log(supportIntlCollator())
Intl.Collator 和 localeCompare 的區(qū)別
當(dāng)需重復(fù)比較大量字符串(如萬(wàn)級(jí)數(shù)組排序)時(shí),Intl.Collator 相比localeCompare更高效。
Intl.Collator適合多次重復(fù)比較,localeCompare 適合單次比較。
因?yàn)?Intl.Collator 預(yù)先緩存語(yǔ)言規(guī)則。
[重要]頻繁排序時(shí),建議緩存collator實(shí)例以提高性能
sort排序會(huì)改變?cè)瓟?shù)組
const nameArr = [
{"text": "北京", "value": "北京"},
{"text": "阿壩州", "value": "阿壩州"},
{"text": "桂林", "value": "桂林"},
{"text": "南寧", "value": "南寧"},
];
const newArr = nameArr.sort((a, b) => a.text.localeCompare(b.text, 'zh-Hans-CN'));
console.log('新數(shù)組', newArr);
console.log('原數(shù)組', nameArr);
轉(zhuǎn)自https://www.cnblogs.com/IwishIcould/p/19023809
該文章在 2025/8/7 10:25:30 編輯過(guò)