We read every piece of feedback, and take your input very seriously.
To see all available qualifiers, see our documentation.
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
最近在使用数组排序的时候,一不小心犯了一个低级错误,分享一下,大家引以为戒。同时,提供一种能应对数组中含有各种特殊符号的排序方式。
在项目中需要将一个数组排序,于是我大致就是这么写的:
//示例,由大到小排序 var ary = [1,3,5,4]; ary.sort(function(a,b){ return a < b; }); //结果:[5,4,3,1]
由于忘记自定义sort函数了,简单在控制台Console里跑了一下,这个是OK的,于是代码就这么去写了,没想到就出问题了。。。
问题是什么呢?看下面的例子:
var ary = [5, 8, 7, 1, 2, 3, 4, 6, 9, 10, 11, 12, 13]; ary.sort(function(a,b){ return a < b; }); //结果:[4, 13, 6, 7, 12, 11, 8, 10, 9, 5, 3, 2, 1]
结果就开始出问题了!
于是仔细看 Array.sort 的API才发现自定义sort函数的返回值并不是 true or false:
Array.sort
true
false
> 0
== 0
< 0
也就是说返回:正数、负数和0!
var ary = [5, 8, 7, 1, 2, 3, 4, 6, 9, 10, 11, 12, 13]; ary.sort(function(a,b){ if (a < b) return 1; if (a > b) return -1; /* else */ return 0; }); //结果:[4, 13, 6, 7, 12, 11, 8, 10, 9, 5, 3, 2, 1]
上面还有一种简写方法,就是:
ary.sort(function(a,b){ return b-a; });
但是这种做法一定要保证数组中全部是 number 类型的,才可以这么简写,要不然最好在function中判断下再处理。
number
比如:
["5", "8", "7", "string", undefined, "3", {}, "6", null, "10", "11", "12", "13"].sort(function(a, b) { return a - b; }); //结果:[null, "3", "5", "6", "7", "8", "10", "11", "12", "string", "13", {…}, undefined]
其实,一般的排序都是针对 数字 的,也就是可以相加减,那么比较起来就比较直观,但是有时候我们排序的内容有可能不只是纯数字,里面可能有字母,甚至中文,这时候怎么办?
数字
JS有个方法:localeCompare,用法参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare
localeCompare
这个方法就是提供本地化的比较方案,详细的使用说明,大家可以看看上面的文档,这里给出一种数组中含有中文、英文、数字、汉字等字符时的通用比较方案。
先给出一组比较复杂的数组:
let testAry = [100,'汉字','中文','澳门',200,'Admin',30,'Lisa',undefined,null,'','%','&'];
先使用传统的方式:
testAry.sort(function(a,b){ return a - b; }); //["", null, 30, "澳门", 100, "Admin", "汉字", "Lisa", "&", "中文", 200, "%", undefined]
当各种情况混合到一起的时候,传统的相减的比较,完全不能达到要求,下来我们看看使用 localeCompare的方案:
testAry.sort(function(a,b){ var r = a - b; if(isNaN(r)){ r = String(a).localeCompare(String(b), 'zh-CN', {sensitivity: 'accent'}); }; return r; }); //["", "&", "%", null, 30, 100, 200, "澳门", "汉字", "中文", "Admin", "Lisa", undefined]
结果明显要好很多,至少除了特殊字符,中英文和数字都是合理的排序,我们稍微改进下,让其按照如下的规则排序,就完美了:
其实,就是将排好序的数组,重新处理下就好了,增加一个方法:
function arySort(ary){ ary.forEach(function(d){ if(!d && d !== 0){ ary.a = ary.a || []; ary.a.push(d); return true; }; if(/\d+/.test(d)){ ary.b = ary.b || []; ary.b.push(d); return true; }; if(/[a-zA-Z]+/.test(d)){ ary.c = ary.c || []; ary.c.push(d); return true; }; //注意:汉字的正则不推荐:/[\u4e00-\u9fa5]/ //参考:https://zhuanlan.zhihu.com/p/33335629 if(/\p{Unified_Ideograph}/u.test(d)){ ary.d = ary.d || []; ary.d.push(d); return true; }; ary.e = ary.e || []; ary.e.push(d); }); return [].concat(ary.b || []) .concat(ary.c || []) .concat(ary.d || []) .concat(ary.e || []) .concat(ary.a || []) };
完整的解决方案代码:
let testAry = [100,'汉字','中文','澳门',200,'Admin',30,'Lisa',undefined,null,'','%','&']; function arySort(ary){ //重新定义ary,不污染外部数组 ary = [].concat(ary); //使用localeCompare排序 ary.sort(function(a,b){ var r = a - b; if(isNaN(r)){ r = String(a).localeCompare(String(b), 'zh-CN', {sensitivity: 'accent'}); }; return r; }); //将排序后的数组重新分类 ary.forEach(function(d){ if(!d && d !== 0){ ary.a = ary.a || []; ary.a.push(d); return true; }; if(/\d+/.test(d)){ ary.b = ary.b || []; ary.b.push(d); return true; }; if(/[a-zA-Z]+/.test(d)){ ary.c = ary.c || []; ary.c.push(d); return true; }; if(/\p{Unified_Ideograph}/u.test(d)){ ary.d = ary.d || []; ary.d.push(d); return true; }; ary.e = ary.e || []; ary.e.push(d); }); return [].concat(ary.b || []) .concat(ary.c || []) .concat(ary.d || []) .concat(ary.e || []) .concat(ary.a || []) }; let result = arySort(testAry); //[30, 100, 200, "Admin", "Lisa", "澳门", "汉字", "中文", "&", "%", "", null, undefined]
下面再验证几个典型的场景:
纯数字
arySort([100,22,0,3,10001]) //[0, 3, 22, 100, 10001]
注意:这里容易出现的错误就是 22 > 100 原因是把这2个按照字符串比较,这样100就排在22前面了。
纯英文
arySort(['hello','world','array','alert','boy','girl']) //["alert", "array", "boy", "girl", "hello", "world"]
注意:alert 和 array,首字母相同时,比较第2个字符,依次类推,这就是字典顺序。
纯中文
arySort(['你好','我们','中国人','比较','腼腆','害羞','奥运']) //["奥运", "比较", "害羞", "腼腆", "你好", "我们", "中国人"]
数字和英文
arySort([100,22,'array','sort',35,'lisa','vivo']) //[22, 35, 100, "array", "lisa", "sort", "vivo"]
中英文和数字
[22, 35, 100, "array", "lisa", "sort", "vivo", "日本", "中国"]
The text was updated successfully, but these errors were encountered:
sunmaobin
No branches or pull requests
最近在使用数组排序的时候,一不小心犯了一个低级错误,分享一下,大家引以为戒。同时,提供一种能应对数组中含有各种特殊符号的排序方式。
问题
在项目中需要将一个数组排序,于是我大致就是这么写的:
由于忘记自定义sort函数了,简单在控制台Console里跑了一下,这个是OK的,于是代码就这么去写了,没想到就出问题了。。。
问题是什么呢?看下面的例子:
结果就开始出问题了!
原因
于是仔细看
Array.sort
的API才发现自定义sort函数的返回值并不是true
orfalse
:> 0
when a is considered larger than b and should be sorted after it== 0
when a is considered equal to b and it doesn't matter which comes first< 0
when a is considered smaller than b and should be sorted before it也就是说返回:正数、负数和0!
解决
上面还有一种简写方法,就是:
但是这种做法一定要保证数组中全部是
number
类型的,才可以这么简写,要不然最好在function中判断下再处理。比如:
深入
其实,一般的排序都是针对
数字
的,也就是可以相加减,那么比较起来就比较直观,但是有时候我们排序的内容有可能不只是纯数字,里面可能有字母,甚至中文,这时候怎么办?JS有个方法:
localeCompare
,用法参考:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/localeCompare这个方法就是提供本地化的比较方案,详细的使用说明,大家可以看看上面的文档,这里给出一种数组中含有中文、英文、数字、汉字等字符时的通用比较方案。
先给出一组比较复杂的数组:
先使用传统的方式:
当各种情况混合到一起的时候,传统的相减的比较,完全不能达到要求,下来我们看看使用
localeCompare
的方案:结果明显要好很多,至少除了特殊字符,中英文和数字都是合理的排序,我们稍微改进下,让其按照如下的规则排序,就完美了:
其实,就是将排好序的数组,重新处理下就好了,增加一个方法:
完整的解决方案代码:
下面再验证几个典型的场景:
纯数字
纯英文
纯中文
数字和英文
中英文和数字
感悟
参考
The text was updated successfully, but these errors were encountered: