js中的数组对象排序分析


Posted in Javascript onDecember 11, 2018

一、普通数组排序

js中用方法sort()为数组排序。sort()方法有一个可选参数,是用来确定元素顺序的函数。如果这个参数被省略,那么数组中的元素将按照ASCII字符顺序进行排序。如:

var arr = ["a", "b", "A", "B"];
arr.sort();
console.log(arr);//["A", "B", "a", "b"]

因为字母A、B的ASCII值分别为65、66,而a、b的值分别为97、98,所以上面输出的结果是 ["A", "B", "a", "b"] 。

如果数组元素是数字呢,结果会是怎样?

var arr = [15, 8, 25, 3];
arr.sort();
console.log(arr);//[15, 25, 3, 8]

结果是 [15, 25, 3, 8] 。其实,sort方法会调用每个数组项的toString()方法,得到字符串,然后再对得到的字符串进行排序。虽然数值15比3大,但在进行字符串比较时"15"则排在"3"前面。显然,这种结果不是我们想要的,这时,sort()方法的参数就起到了作用,我们把这个参数叫做比较函数。

比较函数接收两个参数,如果第一个参数应该位于第二个之前则返回一个负数,如果两个参数相等则返回0,如果第一个参数应该位于第二个之后则返回一个正数。例子:

var arr = [23, 9, 4, 78, 3];
var compare = function (x, y) {//比较函数
 if (x < y) {
 return -1;
 } else if (x > y) {
 return 1;
 } else {
 return 0;
 }
}
console.log(arr.sort(compare));

结果为 [3, 4, 9, 23, 78] ,返回了我们想要的结果。如果要按降序排序,比较函数写成这样即可:

var compare = function (x, y) {
 if (x < y) {
 return 1;
 } else if (x > y) {
 return -1;
 } else {
 return 0;
 }
}

我们并不能用比较函数比较一个不能转化为数字的字符串与数字的顺序:

var arr = ["b", 5];
console.log(arr.sort(compare))

结果是 ["b", 5] 。因为比较函数在比较时,会把先把字符串转化为数字,然后再比较,字符串b不能转化为数字,所以就不能比较大小。然而,当不用比较函数时,会比较ASCII值,所以结果是 [5, "b"] 。

二、数组对象排序

如果数组项是对象,我们需要根据数组项的某个属性对数组进行排序,要怎么办呢?其实和前面的比较函数也差不多:

var arr = [{name: "zlw", age: 24}, {name: "wlz", age: 25}];
var compare = function (obj1, obj2) {
 var val1 = obj1.name;
 var val2 = obj2.name;
 if (val1 < val2) {
 return -1;
 } else if (val1 > val2) {
 return 1;
 } else {
 return 0;
 }  
} 
console.log(arr.sort(compare));

输出结果为 [Object { name="wlz", age=25}, Object { name="zlw", age=24}] ,可以看到数组已经按照 name 属性进行了排序。我们可以对上面的比较函数再改造一下:

var compare = function (prop) {
 return function (obj1, obj2) {
 var val1 = obj1[prop];
 var val2 = obj2[prop];if (val1 < val2) {
  return -1;
 } else if (val1 > val2) {
  return 1;
 } else {
  return 0;
 }  
 } 
}

如果想按照 age 进行排序, arr.sort(compare("age")) 即可。

但是对age属性进行排序时需要注意了,如果age属性的值是数字,那么排序结果会是我们想要的。但很多时候我们从服务器传回来的数据中,属性值通常是字符串。现在我把上面的数组改为:

var arr = [{name: "zlw", age: "24"}, {name: "wlz", age: "5"}];

可以看到,我把 age 属性由数字改为了字符串,第二个数组项的 age 值改为了 "5" 。再次调用 arr.sort(compare("age")) 后,结果为:

[Object { name="zlw", age="24"}, Object { name="wlz", age="5"}]

我们的期望是5排在25前面,但是结果不是。这是因为当两个数字字符串比较大小时,会比较它们的ASCII值大小,比较规则是:从第一个字符开始,顺次向后直到出现不同的字符为止,然后以第一个不同的字符的ASCII值确定大小。所以"24"与"5"比较大小时,先比较”2“与"5"的ASCII值,显然”2“的ASCII值比"5"小,即确定排序顺序。

现在,我们需要对比较函数再做一些修改:

var compare = function (prop) {
 return function (obj1, obj2) {
 var val1 = obj1[prop];
 var val2 = obj2[prop];
 if (!isNaN(Number(val1)) && !isNaN(Number(val2))) {
  val1 = Number(val1);
  val2 = Number(val2);
 }
 if (val1 < val2) {
  return -1;
 } else if (val1 > val2) {
  return 1;
 } else {
  return 0;
 }  
 } 
}

在比较函数中,先把比较属性值转化为数字 Number(val1) 再通过 !isNaN(Number(val1)) 判断转化后的值是不是数字(有可能是NaN),转化后的值如果是数字,则比较转换后的值,这样就可以得到我们想要的结果了, 调用 arr.sort(compare("age")) 得到:

[Object { name="wlz", age="5"}, Object { name="zlw", age="24"}]

可以看到,确实是按正确的方式排序了。

这篇文章所讲的都是基础的,没什么技术含量,只是最近项目中遇到了对数组对象进行排序的问题,所以在这里写出来分享一下,相信总能帮到一些朋友。

Javascript 相关文章推荐
JS模拟多线程
Feb 07 Javascript
JavaScript和JQuery实用代码片段(一)
Apr 07 Javascript
11款新鲜的jQuery插件[附所有demo下载]
Jan 24 Javascript
window.onerror()的用法与实例分析
Jan 27 Javascript
使用Javascript实现选择下拉菜单互移并排序
Feb 23 Javascript
jQuery使用ajax跨域获取数据的简单实例
May 18 Javascript
js实现QQ面板拖拽效果(慕课网DOM事件探秘)(全)
Sep 19 Javascript
微信小程序实现星级评分和展示
Jul 05 Javascript
vue通过video.js解决m3u8视频播放格式的方法
Jul 30 Javascript
js get和post请求实现代码解析
Feb 06 Javascript
JavaScript indexOf()原理及使用方法详解
Jul 09 Javascript
Vue 构造选项 - 进阶使用说明
Aug 14 Javascript
详解Vue源码之数据的代理访问
Dec 11 #Javascript
浅谈Vue 性能优化之深挖数组
Dec 11 #Javascript
vue 内置过滤器的使用总结(附加自定义过滤器)
Dec 11 #Javascript
Vue入门之数量加减运算操作示例
Dec 11 #Javascript
简单的React SSR服务器渲染实现
Dec 11 #Javascript
Vuex 单状态库与多模块状态库详解
Dec 11 #Javascript
微信小程序实现slideUp、slideDown滑动效果及点击空白隐藏功能示例
Dec 11 #Javascript
You might like
php下使用strpos需要注意 === 运算符
2010/07/17 PHP
PHP函数之error_reporting(E_ALL ^ E_NOTICE)详细说明
2011/07/01 PHP
PHP操作MySQL的mysql_fetch_* 函数的常见用法教程
2015/12/25 PHP
PHP抽象类与接口的区别实例详解
2019/05/09 PHP
ext form 表单提交数据的方法小结
2008/08/08 Javascript
js模仿hover的具体实现代码
2013/12/30 Javascript
jQuery函数map()和each()介绍及异同点分析
2014/11/08 Javascript
JavaScript数组和循环详解
2015/04/27 Javascript
javascript实现状态栏文字首尾相接循环滚动的方法
2015/07/22 Javascript
jQuery基于ajax方式实现用户名存在性检查功能示例
2017/02/10 Javascript
React进阶学习之组件的解耦之道
2017/08/07 Javascript
vue实现登录后页面跳转到之前页面
2018/01/07 Javascript
node和vue实现商城用户地址模块
2018/12/05 Javascript
vue项目创建并引入饿了么elementUI组件的步骤
2019/04/11 Javascript
JS数组降维的实现Array.prototype.concat.apply([], arr)
2020/04/28 Javascript
[04:04]显微镜下的DOTA2第六期——电影级别的华丽团战
2014/06/20 DOTA
[01:35]2014DOTA2西雅图邀请赛 专访狐狸妈青春献给刀塔
2014/07/08 DOTA
[02:42]决战东方!DOTA2亚洲邀请赛重启荣耀之争
2017/03/17 DOTA
Python selenium根据class定位页面元素的方法
2019/02/26 Python
Python中的list与tuple集合区别解析
2019/10/12 Python
django使用F方法更新一个对象多个对象字段的实现
2020/03/28 Python
python 画图 图例自由定义方式
2020/04/17 Python
python 实现超级玛丽游戏
2020/11/25 Python
美国经典刺绣和字母儿童服装特卖:Smocked Auctions
2018/07/16 全球购物
法国购买隐形眼镜和眼镜网站:Optical Center
2019/10/08 全球购物
同步和异步有何异同,在什么情况下分别使用他们?举例说明
2014/02/27 面试题
如何打开WebSphere远程debug
2014/10/10 面试题
一套Delphi的笔试题一
2016/02/14 面试题
《罗布泊,消逝的仙湖》教学反思
2014/03/01 职场文书
文秘个人求职信范文
2014/04/22 职场文书
社会实践活动总结
2015/02/05 职场文书
二审答辩状范文
2015/05/22 职场文书
严以修身专题学习研讨会发言材料
2015/11/09 职场文书
体育部部长竞选稿
2015/11/21 职场文书
2016三八妇女节校园广播稿
2015/12/17 职场文书
python+pyhyper实现识别图片中的车牌号思路详解
2022/12/24 Python