JavaScript排序sort()方法(解决null、undefined、0之间的排序(混乱)问题)

文章讨论了JavaScript中使用sort函数对包含空值的对象数组进行排序的问题,指出默认排序可能不包括null和undefined。解决方案是自定义比较函数,处理这些特殊情况。此外,还介绍了双重排序的概念和实现方式,以及如何按照指定顺序和随机顺序对数组进行排序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

sort函数的返回值为经过排序的原始数组的引用。注意数组是就地排序的,不会进行复制。

在这里插入图片描述
在这里插入图片描述

问题:

如果数组内某一对象为空值,排序是怎样的呢?(显然并不是按年龄顺序排序的,因为存在null和undefined)

var arr=[{"age":24,name:'zs'},{"age":0,name:'ls'},{"age":0,name:'gr'}{"age":null,name:'yo'},{"age":7,name:'pl'},{"age":undefined,name:'tt'}{"age":null,name:'jz'},{"age":0,name:'mn'},{"age":undefined,name:'we'}]

//[{"age": 0,"name": "ls"},{"age": 0,"name": "gr"},{"age": null,"name": "yo"},
//{"age": null,"name": "jz"},{"age": 0,"name": "mn"},{"age": 7,"name": "pl"},
//{"age": 24,"name": "zs"},{"age":undefined,"name": "tt"},
//{"age":undefined,"name": "we"}]
console.log(arr.sort(compare("age")));

单纯数组和对象数组的表现还不一样,如下:
在这里插入图片描述

解决方法:

sort 方法提供的排序方法中,如果返回的数字是 0 那么会保持原顺序,如果返回的数字 >0 那么会将 a 至于 b 之后,如果返回的数字 < 0 那么会将 a 至于 b 之前。

如果遇到字段可能是 undefined,那么我们需要特殊判断处理下。

首先判断如果 a,b 的排序字段都是 undefined 返回 0 保持原顺序。

再判断如果 a 的字段是 undefined 但 b 的排序字段存在则返回 >0 将 a 至于 b 之后。

再判断 b 的排序字段如果是 undefined 但 a 的排序字段存在则返回 <0 将 a 至于 b 之前。

最后 a,b 的排序字段都存在时,使用 a,b 的排序字段计算后的返回结果判断顺序

const compare = function (orderType, props) {
    return function (obj1, obj2) {
        var val1 = obj1[props];
        var val2 = obj2[props];
        if (val1 == null && val2 == null) {
            return 0;
        }
        if(val1 == null){
            return 999;
	    }
	    if(val2 == null){
	        return -999
	    }
        if (typeof val1 === 'string' && typeof val2 === 'string') {
            if (val1 < val2) {
                return -1;
            } else if (val1 > val2) {
                return 1;
            }
            return 0;
        }
	    return orderType === 'ascend' ? val1 - val2 : val2 - val1;
    } 
}
const orderType = 'descend'; // descend
const rr = prodInfo.sort(compare(orderType, 'num'))
console.log(rr.map(item => item.num))

参考链接1:https://www.cnblogs.com/gby-web/p/16743564.html
参考链接2:https://juejin.cn/post/7165121725678665765/


双重排序(二次排序):

二次排序是指对数据进行两次排序,第一次按照某个属性进行排序,第二次按照另一个属性进行排序。这种排序方法可以用于多种场景,例如对学生按照成绩和年龄进行排序,对商品按照价格和销量进行排序等等。在实现二次排序时,可以使用多种算法,例如冒泡排序、快速排序、归并排序等等。需要根据具体的场景和数据量选择最适合的算法。

/**
 * 二次排序
 */

const productInfo = [
    {
        category: 'apple',
        price: 5
    }, {
        category: 'apple',
        price: undefined
    }, {
        category: 'apple',
        price: 2
    }, {
        category: 'pear',
        price: undefined
    }, {
        category: 'grape',
        price: null
    }, {
        category: 'banana',
        price: 7
    }, {
        category: 'orange',
        price: 3
    }
]


// 初版
// const orderProdInfo = productInfo.sort((a, b) => {
//     if (a['category'] < b['category']) {
//         return -1;
//     } else if (a['category'] > b['category']) {
//         return 1;
//     } else {
//         // 第一层排序相等情况,处理第二层排序
//         return a['price'] - b['price']
//     }
    
// });
// console.log(productInfo)


// 函数抽取
function compareCore(compareFn) {
   return (l, r) => {
        if (l == null && r == null) {
            return 0;
        }
        if (l == null && r) {
            return 1
        }
        if (l && r == null) {
            return -1;
        }
        return compareFn(l, r);
   }

}

const numberCompare = compareCore((l, r) => l - r);
const stringCompare = compareCore((l, r) => {
    if (l < r) {
        return -1;
    } else if (l > r) {
        return 1;
    } else {
        return 0;
    }
})

// 业务逻辑
const priceCompare = (l, r) => {
    return numberCompare(l['price'], r['price'])
}
const cateCompare = (l, r) => {
    return stringCompare(l['category'], r['category']);
}
// 双重排序
const doubleCompare = (l, r) => {
    if (cateCompare(l, r) === 0) {
        return priceCompare(l, r);
    }
    return cateCompare(l, r);
}
const orderProdInfo = productInfo.sort((l, r) => {
    return doubleCompare(l, r)
});
console.log(orderProdInfo)

指定顺序排序

// ## 按指定序列排序
const arr = [
    { name: 'A', type: 'fly' },
    { name: 'B', type: 'blur' },
    { name: 'C', type: 'wipe' },
    { name: 'D', type: 'cube' },
    { name: 'B', type: 'zoom' },
    { name: 'C', type: 'cube' },
    { name: 'E', type: 'iris' },
    { name: 'F', type: 'fade' },
    { name: 'F', type: '' }
];
// 按type的指定顺序排序
const order = ['wipe', 'fly', 'iris', 'flip', 'cube', 'blur', 'fade', 'zoom'];
arr.sort((star, next) => {
    return order.indexOf(star.type) - order.indexOf(next.type);
});

console.log(arr);

随机排序

// ## 随机排序
arr.sort((a, b) => {
    return Math.random() - 0.5
}) 
console.log(arr);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

. . . . .

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值