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 相关文章推荐
JavaScript高级程序设计(第3版)学习笔记 概述
Oct 11 Javascript
JS在TextArea光标位置插入文字并实现移动光标到文字末尾
Jun 21 Javascript
JavaScript中的console.assert()函数介绍
Dec 29 Javascript
JS+CSS实现类似QQ好友及黑名单效果的树型菜单
Sep 22 Javascript
基于JavaScript实现智能右键菜单
Mar 02 Javascript
基于jquery实现最简单的选项卡切换效果
May 08 Javascript
jQuery遍历json的方法(推荐)
Jun 12 Javascript
详解使用angularjs的ng-options时如何设置默认值(初始值)
Jul 18 Javascript
微信小程序自动客服功能
Nov 02 Javascript
jQuery实现当拉动滚动条到底部加载数据的方法分析
Jan 24 jQuery
express框架中使用jwt实现验证的方法
Aug 25 Javascript
countUp.js实现数字动态变化效果
Oct 17 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
优化NFR之一 --MSSQL Hello Buffer Overflow
2006/10/09 PHP
Php获取金书网的书名的实现代码
2010/06/11 PHP
hadoop常见错误以及处理方法详解
2013/06/19 PHP
windows下配置apache+php+mysql时出现问题的处理方法
2014/06/20 PHP
PHP实现服务器状态监控的方法
2014/12/09 PHP
PHP抽奖算法程序代码分享
2015/10/08 PHP
Yii2中hasOne、hasMany及多对多关联查询的用法详解
2017/02/15 PHP
laravel ORM 只开启created_at的几种方法总结
2018/01/29 PHP
js的闭包的一个示例说明
2008/11/18 Javascript
capacityFixed 基于jquery的类似于新浪微博新消息提示的定位框
2011/05/24 Javascript
Prototype源码浅析 Enumerable部分(二)
2012/01/18 Javascript
用javascript模仿ie的自动完成类似自动完成功的表单
2012/12/12 Javascript
jQuery实现鼠标点击弹出渐变层的方法
2015/07/09 Javascript
js+css绘制颜色动态变化的圈中圈效果
2016/01/27 Javascript
jQuery插件Easyui设置datagrid的pageNumber导致两次请求问题的解决方法
2016/08/06 Javascript
jQuery插件HighCharts绘制2D金字塔图效果示例【附demo源码下载】
2017/03/09 Javascript
简单谈谈关于 npm 5.0 的新坑
2017/06/08 Javascript
vue组件中watch props根据v-if动态判断并挂载DOM的问题
2019/05/12 Javascript
layui 解决form表单点击无反应的问题
2019/10/25 Javascript
聊聊Vue中provide/inject的应用详解
2019/11/10 Javascript
用Python解决计数原理问题的方法
2016/08/04 Python
Python中字符串格式化str.format的详细介绍
2017/02/17 Python
python利用paramiko连接远程服务器执行命令的方法
2017/10/16 Python
一个简单的python爬虫程序 爬取豆瓣热度Top100以内的电影信息
2018/04/17 Python
Django实现WebSSH操作物理机或虚拟机的方法
2019/11/06 Python
基于Python检测动态物体颜色过程解析
2019/12/04 Python
python爬取网易云音乐热歌榜实例代码
2020/08/07 Python
matplotlib实现数据实时刷新的示例代码
2021/01/05 Python
荷兰在线钓鱼商店:Raven
2019/06/26 全球购物
金融专业求职信
2014/08/05 职场文书
报效祖国演讲稿
2014/09/15 职场文书
2014年扫黄打非工作总结
2014/12/03 职场文书
公务员考察材料范文
2014/12/23 职场文书
2016基督教会圣诞节开幕词
2016/03/04 职场文书
浅谈如何写好演讲稿?
2019/06/12 职场文书
《王者天下》第4季首话新剧照 4月9日正式开播
2022/04/07 日漫