让我们来看一个例子:
var arr = [1,2,4,7,21,45];
arr.sort(); //[1, 2, 21, 4, 45, 7]
arr.sort(function(a,b){
return a-b;
}) //[1, 2, 4, 7, 21, 45]
复制代码
这个结果让我很疑惑,上面的代码第一个sort没有按照数值的大小对数字进行排序,而第一个sort就是我们就要的结果。查了下资料关于sort()的解释如下:
sort()
对数组的元素先调用toString方法,再按照字符串的Unicode编码进行排序。 这样就很好理解上面的例子了:sort()方法默认是按照unicode编码来进行比较的,而不是按照我们想的比较两个数值间的大小来进行排序了。 如果想按照其他标准进行排序,就需要提供比较函数,该函数比较两个值,然后返回一个用于说明这两个值的相对顺序的数字。比较函数应该具有两个参数a和b,其返回值如下:
- 若a小于b,在排序后的数组中 a 应该出现在 b 之前,则返回一个小于 0 的值。
- 若a等于b,则返回 0。
- 若a大于b,则返回一个大于 0 的值。
那假如我们想根据数组对象中的某个属性值进行排序呢?
sort方法接收一个函数作为参数,这里嵌套一层函数用来接收对象属性名,其他部分代码与正常使用sort方法相同。如下:
var arr = [
{name:'zopp',age:0},
{name:'gpp',age:18},
{name:'yjj',age:8}
];
function compare(property){
return function(a,b){
var value1 = a[property];
var value2 = b[property];
return value1 - value2;
}
}
console.log(arr.sort(compare('age')))
复制代码
结果如图所示:
PS:V8 引擎 sort 函数只给出了两种排序InsertionSort(插入排序)和QuickSort(快速排序),数量小于10的数组使用InsertionSort,比10大的数组则使用 QuickSort。
利用JavaScript对中文(汉字)进行排序
在网页上展示列表时经常需要对列表进行排序:按照修改/访问时间排序、按照地区、按照名称排序。
对于中文列表按照名称排序就是按照拼音排序,不能简单通过字符串比较—— ‘a' > ‘b'——这种方式来实现。
比如比较 ‘北京' vs ‘上海',实际是比较 ‘běijīng' vs ‘shànghǎi';比较 ‘北京' vs ‘背景',实际是比较 ‘běijīng' vs ‘bèijǐng'。
一般需要获取到字符串的拼音,再比较各自的拼音。
实现方法:
JavaScript 提供本地化文字排序,比如对中文按照拼音排序,不需要程序显示比较字符串拼音。String.prototype.localeCompare在不考虑多音字的前提下,基本可以完美实现按照拼音排序。
localecompare
string.localCompare(target, locals)
复制代码
用本地特定的顺序来比较两个字符串,若a>b,返回大于0的数,若相等返回0。
var str1 = 'beijing',
str2 = '北京',
str3 = '背景',
str4 = '北方';
str1.localecompare(str2); //1
str2.localecompare(str3); //1
str3.localecompare(str2); //-1
str4.localecompare(str2); //-1
str4.localecompare(str3); //-1
复制代码
从上面可以看出,localCompare是根据我们的中文系统,把汉字先转换成了拼音,再进行了比较;对于同拼音的汉字,js再根据声调进行比较。
在没有出现意外的情况下,各个支持 localeCompare 的浏览器都很正常。最近将 Chrome 更新到 58.0.3029.110,突然发现中文排序不正常。
// 正常应该返回 1, 拼音 jia 在前, kai 在后
'开'.localeCompare('驾');
// 得到
-1;
// Chrome 58.0.3029.110 下返回 -1, 其他浏览器正常
// 确认之后是 localeCompare 需要明确指定 locales 参数
'开'.localeCompare('驾', 'zh');
// 得到
1
复制代码