方法是先把中文轉換成拼音而後根據拼音排序。html
關於中文轉拼音請看上一篇,中文轉拼音,此處的PinYin變量就是這篇文章中的的拼音庫。數組
用戶給定的數據會有數字英文和漢字。spa
無論是字符排序仍是真個字符串的排序都是採用補全數字的方法,這裏稱呼獲得的位置先後的叫權重吧,權重小的在前(就是數字小的),權重大的在後(就是數字大的)首先計算全部的可能。code
0-9(10),a-z(25),A-Z(25) ,漢字(390多個),其它(1)加起來小於1000 ,就用4位補全。orm
// ascII 0-9 -> 48-57 A-Z -> 65-90 a-z -> 97-122
0就對應着0048,z對應着0122,漢字拼音從200開始,拼音a對應 0200,其它權重最小0001,下面是生成這個權重對象的代碼。htm
字符權重的長度位4,就是‘0000’;對象
由於英文和漢字拼音有重複的須要區分開,將拼音前面加 '_'blog
var getCharPriority = function (preNum) { return ('0000'+ preNum).substr(-4); }; var getCharPriorityObj = function () { var obj = {}; // 0-9 A-Z a-z 的權重 for(var i =48; i < 123; i++ ) { if(i < 58 || (i > 64 && i < 91) || i > 96) { obj[String.fromCharCode(i)] = getCharPriority(i); } } // 拼音的權重 i = 200; // 由於英文和漢字拼音有重複的須要區分開,將拼音前面加 '_' for(var key in PinYin) { obj['_' + key] = getCharPriority(i ++); } // 其它的權重 obj._other = '0001'; return obj; };
而後是對字符串的排序,排除數組中的數字和英文(單獨排序);排序
對於給定的中文取最長的字符串的長度做爲補足的長度。比方說 ‘李’和‘李明’,那比較的長度就是2,每一個字符4位就須要補足2 * 4 8位。ip
因爲排序的規則是短的在前面,就是短的權重高,因此字符串的補足權重的規則就是從開始截取而且補足的數字是最大的。好比
李 -> 0248 補完權重就是02489999; // 補4個000
李明 -> 02480344
下面是字符串權重權重的方法。(最大長度定位6,根據傳入狀況區分長度沒有寫)
var maxStrLength = 6; var complimentStr = ''; for(var i = 0;i < maxStrLength; i++) { complimentStr += '0000'; } function getStrPriority(str) { return (str + complimentStr).substr(0,6 * 4); }
接下來就是寫這個排序的方法,傳入的參數是一個數組。
首先區分漢字和普通的數字和字母組合,分別放入兩個數組中
// 將原來的字符串轉換成對象 // 'aa' -> {'str': 'aa',priority: ''} for(var i = 0; i < arr.length; i++) { fakeArr.push({ str: arr[i], priority: getCurStrPriority(arr[i]) }); } fakeArr.sort(function (item1,item2) { return ('1' + item1.priority) - ('1' + item2.priority); });
var otherArr = [];
for(var i = 0,len = fakeArr.length; i < len; i ++) {
otherArr.push(fakeArr[i]);
}
return otherArr;
} var charPriorityObj = getCharPriorityObj(); var getChar = function (char) { var reg = /[0-9a-zA-Z]/; var result; if (reg.test(char)) { result = char; } else if ((result = pinyinTool.getPinYin(char)) === -1) { result = '_other'; } return result }; function getCurStrPriority(str) { //遍歷str 計算每一個字符的權重 var priority = ''; for(var i = 0; i < str.length; i ++) { priority += charPriorityObj['_' + getChar(str[i])]; } return priority; } function sorAll(arr) { // 區分數字字母和拼音 var collect = { normal: [], pinyin: [] }; var reg = /^[a-zA-Z0-9]+$/g; for(var i = 0,len = arr.length; i < len; i ++) { var curstr = arr[i]; if(reg.test(curstr)) { collect.normal.push(curstr); }else { collect.pinyin.push(curstr); } } // 對數字字母排序 collect.normal.sort(String.localeCompare); collect.pinyin = pinyinCompare(collect.pinyin); // 排序 return collect.normal.concat(collect.pinyin); }
完整的代碼:
var pinyinTool = (function() { // 首字母大寫 var ucfirst = function (char) { return char = char.replace(/./, function (match) { return match.toUpperCase(); }); }; // 在對象中搜索 var getPinYin = function (char) { for (var name in PinYin) { if (PinYin[name].indexOf(char) !== -1) { return name; } } return -1; }; var getCharPriority = function (preNum) { return ('0000'+ preNum).substr(-4); }; var getCharPriorityObj = function () { var obj = {}; // 0-9 A-Z a-z 的權重 for(var i =48; i < 123; i++ ) { if(i < 58 || (i > 64 && i < 91) || i > 96) { obj[String.fromCharCode(i)] = getCharPriority(i); } } // 拼音的權重 i = 200; // 由於英文和漢字拼音有重複的須要區分開,將拼音前面加 '_' for(var key in PinYin) { obj['_' + key] = getCharPriority(i ++); } // 其它的權重 obj._other = '0001'; return obj; }; var charPriorityObj = getCharPriorityObj(); var maxStrLength = 6; var complimentStr = ''; for(var i = 0;i < maxStrLength; i++) { complimentStr += '0000'; } function pinyinCompare(arr) { var fakeArr = []; // 將原來的字符串轉換成對象 // 'aa' -> {'str': 'aa',priority: ''} for(var i = 0; i < arr.length; i++) { fakeArr.push({ str: arr[i], priority: getCurStrPriority(arr[i]) }); } fakeArr.sort(function (item1,item2) { return ('1' + item1.priority) - ('1' + item2.priority); }); var otherArr = []; for(var i = 0,len = fakeArr.length; i < len; i++) { otherArr.push(fakeArr[i].str); } return otherArr; } var getChar = function (char) { var reg = /[0-9a-zA-Z]/; var result; if (reg.test(char)) { result = char; } else if ((result = getPinYin(char)) === -1) { result = '_other'; } return result }; function getStrPriority(str) { return (str + complimentStr).substr(0,6 * 4); } function getCurStrPriority(str) { //遍歷str 計算每一個字符的權重 var priority = ''; for(var i = 0; i < str.length; i ++) { priority += charPriorityObj['_' + getChar(str[i])]; } return getStrPriority(priority); } return { convertToPinYin: function (inputStr,isFirstUpper) { var len = inputStr.length; var result = ''; var reg = /[a-zA-Z0-9\- ]/; var pinyin; for (var i = 0; i < len; i++) { var curChar = inputStr[i]; result += reg.test(curChar) || (pinyin = getPinYin(curChar)) === -1 ? curChar : isFirstUpper ? ucfirst(pinyin) : pinyin; } return result; }, sort: function (arr) { // 區分數字字母和拼音 var collect = { normal: [], pinyin: [] }; var reg = /^[a-zA-Z0-9]+$/; for(var i = 0,len = arr.length; i < len; i ++) { var curstr = arr[i]; if(reg.test(curstr)) { collect.normal.push(curstr); }else { collect.pinyin.push(curstr); } } // 對數字字母排序 collect.normal.sort(function(str1,str2){ return str1.localeCompare(str2); }); collect.pinyin = pinyinCompare(collect.pinyin); // 排序 return collect.normal.concat(collect.pinyin); } }; })();