浅谈JS原生Sort实现业务中的排序

一、基本使用

const arrNum=[5,3,6,100,6,7];

Array类型的对象都有sort方法。当定义了如上的arrNum,可以直接使用sort方法,例

注意:sort方法是会影响源数据的 

sort方法中可以传入一个“compareFunction”,函数有两个参数a、b,表示在sort排序过程中一组组做对比的前后两个对象。可以理解为遍历中的“i”和“i+1”。

arrNum.sort(function(a,b){ // 升序写法
    if(a < b){
        return -1;   
    }
    if(a > b){
        return 1;
    }
    if(a === b){
        return 0;
    }
})

在compareFunction函数里,return的值“x”,有如下规则

1、x<0时则会将a移动到b前面。2、x>0时则会将a移动到b后面。3、如果x=0则位置不变。

所以上面代码可以简写如下:a、b前后两数相减,正数表示原来顺序在前的比后面的大,则会后移一位。依次比较下去则完成了升序。

arrNum.sort(function(a, b){ // 升序写法
    return a - b;
});
//附:箭头函数更简化,不懂得自行了解
//arrNum.sort((a, b)=> a - b);

要做降序,函数接收参数时,只需要把a、b的声明换个位置,如compareFunction(b,a)

二、对象排序

const arrObj=[{
  name:'史密斯',
  age:18,
  birthday:'2003-01-08'
},{
  name:'丹妮',
  age:16,
  birthday:'2005-06-08'
},{
  name:'艾米',
  age:24,
  birthday:'1997-07-08'
}];

这时的a、b就是对象数组中的某两个对象元素,均可以点到其元素的属性。如下拿年龄升序

arrObj.sort((a,b)=> a.age - b.age);

三、时间、中文排序

在上面的对象排序中存在时间和中文,无法直接相减做排序,需要特殊处理

1)Date类型把他转化为时间戳,就是一串数字,就可以按数字排序了,例

arrObj.sort((a,b)=> { // 升序
  return new Date(a.birthday).getTime() - new Date(b.birthday).getTime();
});

2)中文则需要利用localeCompare()函数比较两个字符在字母表中排序,如果String a在Param b前则返回-1,相等则0,否则1。

arr.sort((a, b) => { // Z-A排序
   return a.name.localeCompare(b.name, 'zh');
});

注意 :按localeCompare来比较中文会有bug:多音字的问题,长沙,重庆这种,系统取的是zhang和zhong的拼音。所以导致排序时这种字会垫底。

四、实用封装

上代码,测试用例直接弄他,代码在线测试正则在线测试

/**对对象数组排序
 *arr:要排序的数据源,key:数据源中排序的键名,type:排序方式(默认升序)
 */
function sortObjArr(arr, key, type = 'asc', special = 'emptyAfter') {
  if(arr&&arr.length){
  	const noNullObj=arr.find(x=>x[key]); // 找一个不为空的该字段的对象
    if (isDate(noNullObj[key])) { // 日期时间类型
        // ||/^(date|time)|(date|time)$/gi.test(str) // 或者说这个字段名包含了date或者time
      arr.sort((a, b) => {
        if (type === 'asc') { // 升序
          return new Date(a[key]).getTime() - new Date(b[key]).getTime();
        }
        return new Date(b[key]).getTime() - new Date(a[key]).getTime();
      });
    } else if (isNaN(noNullObj[key])) { // 中文或字母等
      arr.sort((a, b) => {
        if (type === 'desc') { // 降序
          return a[key].localeCompare(b[key],'zh');
        }
        return b[key].localeCompare(a[key],'zh');
      });
    } else {// 其他数值
      arr.sort((a, b) => {
        if (type === 'asc') {
          return a[key] - b[key];
        }
        return b[key] - a[key];
      });
    }
  }
  if(special==='emptyAfter'){// 空值移到最后
    arr.sort((a,b)=>{
      if(a[key] && b[key]){
        return 0;
      }
      return -1; // 有一个为空则往后移
    });
  }
  return arr;
}
sortObjArr(arrObj,'name','desc');
console.log('名字降序',arrData);

function isDate(str){ // 判断是否日期
  if(str instanceof Date // 是原始日期类型
    ||(/^\d{4}(-|\/){1}\d{1,2}(-|\/){1}\d{1,2}/.test(str)&&new Date(str)) 
    ){ // 符合正则的2021-01-02
     return true;
   }
  return false;
}

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值