方法是先把中文转换成拼音然后根据拼音排序。
关于中文转拼音请看上一篇,中文转拼音,此处的PinYin变量就是这篇文章中的的拼音库。
用户给定的数据会有数字英文和汉字。
不管是字符排序还是真个字符串的排序都是采用补全数字的方法,这里称呼得到的位置前后的叫权重吧,权重小的在前(就是数字小的),权重大的在后(就是数字大的)首先计算所有的可能。
首先是每个字符的排序,包括 0-9,a-z,A-Z,和汉字,无法识别的字符(特殊字符和无法识别的汉字)。
0-9(10),a-z(25),A-Z(25) ,汉字(390多个),其它(1)加起来小于1000 ,就用4位补全。
// ascII 0-9 -> 48-57 A-Z -> 65-90 a-z -> 97-122
0-9,a-z,A-Z,可以根据ascII码来区分
0就对应着0048,z对应着0122,汉字拼音从200开始,拼音a对应 0200,其它权重最小0001,下面是生成这个权重对象的代码。
字符权重的长度位4,就是‘0000’;
因为英文和汉字拼音有重复的需要区分开,将拼音前面加 '_'
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位。
由于排序的规则是短的在前面,就是短的权重高,所以字符串的补足权重的规则就是从开始截取并且补足的数字是最大的。比如
李 -> 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); }
接下来就是写这个排序的方法,传入的参数是一个数组。
首先区分汉字和普通的数字和字母组合,分别放入两个数组中
- 数字字母数组用 String.localeCompare 方法比较或者用上述的权重补全方法;
- 其它的使用字符串补全的办法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]);
}
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); } }; })();