2023-04-01 解决使用sort()方法对数字数组排序失效的问题,sort()方法的参数:比较函数,如何根据对象属性,将对象构成的数组进行排序?

文章目录

        • 0.回顾sort()的用法
          • 示例一:对字符数组进行排序
          • 示例二:对数字数组进行排序
        • 1.sort()无法对由两位数以上的数组元素构成的数组进行合理排序
          • 示例
          • 出现原因和解决方法
        • 2.sort()的参数——比较函数
          • 示例:使用比较函数将数字数组进行正确排序
          • 比较函数的参数
          • 比较函数不能对混搭(字符+数字)数组进行排序
        • 3.对于由对象构成的数组,如何排序?
          • 需求
          • 解决方法:使用比较函数
          • 改进一:此时只能针对age属性进行排序,把age也替换成形参,写法如下
          • 改进二:让比较函数可以使用 属性值是数字型字符串的对象属性 作为根据,进行数组排序

0.回顾sort()的用法

sort()方法是用于数组排序的,语法如下:array.sort(),
使用sort()方法后会改变原数组的顺序(而不是生成一个新数组,同时原数组保持不变)

示例一:对字符数组进行排序
    var myarr1=["h","e","l","l","o"];
    myarr1.sort();
    console.log(myarr1);//(5) ['e', 'h', 'l', 'l', 'o']

sort中没有参数时,会按照数组元素对应的ASCII码进行比较和排序

示例二:对数字数组进行排序
    var myarr2=[9,5,1,4,6];
    myarr2.sort();
    console.log(myarr2);//(5) [1, 4, 5, 6, 9]

1.sort()无法对由两位数以上的数组元素构成的数组进行合理排序

示例
    var myarr2=[10,25,3,8];
    myarr2.sort();
    console.log(myarr2);//10 25 3 8
出现原因和解决方法

因为sort()方法会首先会调用每个数组数据项的toString()方法,
转换成字符串以后再进行比较,在字符串中"25"<“3”,
解决方法是需要用到sort的参数,此时这个参数叫做比较函数

2.sort()的参数——比较函数

示例:使用比较函数将数字数组进行正确排序
 	var myarr2=[10,25,3,8];
    var mycompare=function (x,y){
      if(x<y) return -1;
      else if(x>y) return 1
      else return 0;
    };
    myarr2.sort(mycompare);
    console.log(myarr2);//(4) [3, 8, 10, 25]
比较函数的参数

比较函数会接受两个参数,并对两者进行比较

  • 若第一个参数应位于第二个参数之前,则返回一个负数
  • 若第一个参数等于第二个参数,则返回0
  • 若第一个参数应位于第二个参数之后,则返回一个正数

通过以上逻辑的比较函数,会使数组最后变为升序排列,
若要变为降序,只需返回一个负数变为返回一个正数即可(正数变负数,负数变正数)

比较函数不能对混搭(字符+数字)数组进行排序
    var myarr3=["h",10];
    myarr3.sort(mycompare);
    console.log(myarr3);//(2) ['h', 10]
    myarr3.sort();
    console.log(myarr3);//(2) [10, 'h']

不能将比较函数用于比较一个不能转化成数字的字符串和数组的排序,
这是因为比较函数会先将字符串转化成数字再比较,当字符串不能转换成数字时,就不能比较大小(不用比较函数,也就是sort不加参数时,比较的是ASCII值,此时可以比较)
正确用法:

    // 对于不能转换成数字的字符串(字母型字符串),不使用比较参数,直接比较ASCII值
    var myarr3=["h",10];
    myarr3.sort();
    console.log(myarr3);//(2) ['h', 10]
    // 对于可以转换成数字的字符串(数字型字符串),使用比较函数转换成数字再比较
    var myarr4=["23",37,"1",14];
    myarr4.sort(mycompare);
    console.log(myarr4);//(4) ['1', 14, '23', 37]

总结:
数组中既有字符串又有数字时,先看看其中的字符串是字母型字符串还是数字型字符串,

若是字母型字符串,sort不用带参数,直接比较ASCII值
若是数字型字符串,sort带参数,让比较函数将字符串转换成数字再比较

3.对于由对象构成的数组,如何排序?

需求

数组项是对象,现在需要根据对象的某个属性,对数组进行排序

	//要求根据对象属性age对数组进行排序
    var arr=[
      {age:10,name:'Tom'},
      {age:8,name:'Jack'},
      {age:20,name:'Michel'},
      {age:12,name:'Daniel'},
    ];
解决方法:使用比较函数
    var compare = function (obj1, obj2) {
        if (obj1.age < obj2.age) return -1;
        else if (obj1.age > obj2.age) return 1;
        else return 0;
    } 
    console.log(arr.sort(compare));

效果:

{age: 8, name: 'Jack'}
{age: 10, name: 'Tom'}
{age: 12, name: 'Daniel'}
{age: 20, name: 'Michel'}
改进一:此时只能针对age属性进行排序,把age也替换成形参,写法如下
    var compare = function (prop){
      return function (obj1, obj2) {
        if (obj1.age < obj2.age) return -1;
        else if (obj1.age > obj2.age) return 1;
        else return 0;
      } 
    }
    console.log(arr.sort(compare('age')));//调用比较函数时要指定对象属性

此时仍有一个缺点,若对象属性age中的属性值从数字变为字符串(25==>“25”),那么仍然不会得到正确排序,因为两个数字型字符串比较大小时会比较它们的ASCII大小,而我们期望的结果是它们转换成数字后比较大小
因此仍需给比较函数再进行改进

改进二:让比较函数可以使用 属性值是数字型字符串的对象属性 作为根据,进行数组排序
    var arr2=[{age:"25",name:"zhangsan"},{age:"9",name:"lisi"}];
    var compare = function (prop){
      return function (obj1, obj2) {
        var val1 = obj1[prop], 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;
      } 
    }
    console.log(arr2.sort(compare('age')));

效果:

{age: '9', name: 'lisi'}
{age: '25', name: 'zhangsan'}

以上就是对数组对象进行排序的最终比较函数的代码

你可能感兴趣的:(bug&error,知识点,javascript,数组,sort,比较函数,Array)