# 经验分享-Array.sort高级用法 #43

Open
opened this Issue Dec 12, 2017 · 0 comments

Projects
1 participant
Owner

## 问题

//示例，由大到小排序
var ary = [1,3,5,4];
ary.sort(function(a,b){
return a < b;
});
//结果：[5,4,3,1]

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]

## 原因

• > 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

## 解决

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;
});

["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

testAry.sort(function(a,b){
return a - b;
});
//["", null, 30, "澳门", 100, "Admin", "汉字", "Lisa", "&", "中文", 200, "%", undefined]

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 || [])
};

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]

1. 纯数字

arySort([100,22,0,3,10001])
//[0, 3, 22, 100, 10001]

注意：这里容易出现的错误就是 22 > 100
原因是把这2个按照字符串比较，这样100就排在22前面了。

2. 纯英文

//["alert", "array", "boy", "girl", "hello", "world"]

3. 纯中文

arySort(['你好','我们','中国人','比较','腼腆','害羞','奥运'])
//["奥运", "比较", "害羞", "腼腆", "你好", "我们", "中国人"]
4. 数字和英文

arySort([100,22,'array','sort',35,'lisa','vivo'])
//[22, 35, 100, "array", "lisa", "sort", "vivo"]
5. 中英文和数字

[22, 35, 100, "array", "lisa", "sort", "vivo", "日本", "中国"]

## 感悟

• 基础很重要，要时不时翻翻API，看看书；
• 遇到模糊的概念，最好先翻翻API再下手。