JavaScript数组对象排序没有按预期工作

JavaScript Array Object Sort not working as expected

本文关键字:工作 数组 对象 排序 JavaScript      更新时间:2023-09-26

我的数组对象如下

 var data = [{"weight":0,"name":"New Arrivals"},{"weight":0,"name":"Weekly Promotions"},{"weight":0,"name":"Sale"},{"weight":0,"name":"Extended Size"},{"weight":0,"name":"Accessories and Shoes"},{"weight":0,"name":"Activewear"},{"weight":0,"name":"Disney Project"},{"weight":0,"name":"Dresses and Jumpsuits"},{"weight":0,"name":"Fleece"},{"weight":0,"name":"HEATTECH Collection"},{"weight":0,"name":"Ines de la Fressange"},{"weight":0,"name":"Intimates"},{"weight":0,"name":"Jeans"},{"weight":0,"name":"Loungewear"},{"weight":0,"name":"Outerwear and Blazers"},{"weight":0,"name":"Pants"},{"weight":0,"name":"Shirts and Blouses"},{"weight":0,"name":"Skirts"},{"weight":0,"name":"Socks and Hosiery"},{"weight":0,"name":"Sweaters"},{"weight":0,"name":"Sweatshirts and Sweatpants"},{"weight":0,"name":"T-Shirts and Tops"},{"weight":0,"name":"UT: Graphic Tees"},{"weight":0,"name":"Wear To Work"},{"weight":0,"name":"Mix and Match"}]

我试图根据属性权重对其进行排序,但如果权重的所有值都为0,我需要原始顺序,因为它是在输出上。但是这个功能没有像预期的那样工作,而是顺序发生了变化。

使用过ramda和JavaScript排序

var sortedData = R.sortBy(R.prop('weight'), data);

var sortData = data.slice(0);
sortData.sort(function(a,b) {
    return a.weight - b.weight;
});

两种情况下得到的结果如下

var output = [{"weight":0,"name":"Jeans"},{"weight":0,"name":"New Arrivals"},{"weight":0,"name":"Sale"},{"weight":0,"name":"Extended Size"},{"weight":0,"name":"Accessories and Shoes"},{"weight":0,"name":"Activewear"},{"weight":0,"name":"Disney Project"},{"weight":0,"name":"Dresses and Jumpsuits"},{"weight":0,"name":"Fleece"},{"weight":0,"name":"HEATTECH Collection"},{"weight":0,"name":"Ines de la Fressange"},{"weight":0,"name":"Intimates"},{"weight":0,"name":"Weekly Promotions"},{"weight":0,"name":"Loungewear"},{"weight":0,"name":"Outerwear and Blazers"},{"weight":0,"name":"Pants"},{"weight":0,"name":"Shirts and Blouses"},{"weight":0,"name":"Skirts"},{"weight":0,"name":"Socks and Hosiery"},{"weight":0,"name":"Sweaters"},{"weight":0,"name":"Sweatshirts and Sweatpants"},{"weight":0,"name":"T-Shirts and Tops"},{"weight":0,"name":"UT: Graphic Tees"},{"weight":0,"name":"Wear To Work"},{"weight":0,"name":"Mix and Match"}]

期望值:当权重值为0的所有情况下,那么我期望的结果与输入相同。

感谢您的帮助。

你的问题是JavaScript中的排序不能保证稳定。ECMA-262规范以以下方式声明:

数组中的元素已排序。排序不一定是稳定的(也就是说,比较结果相等的元素不一定保持原来的顺序)。

在javascript中实现快速稳定排序算法的问题包含一个链接到这篇Vjeux博客文章,该文章谈到了稳定排序以及其他几个选项。

使用map排序的建议。在这里,您有了索引,并保留了使用第二个链式排序标准的原始排序。

mapped.sort(function (a, b) {
    return a.value - b.value || a.index - b.index;
});

// the array to be sorted
var data = [{ weight: 0, name: "New Arrivals" }, { weight: 0, name: "Weekly Promotions" }, { weight: 0, name: "Sale" }, { weight: 0, name: "Extended Size" }, { weight: 0, name: "Accessories and Shoes" }, { weight: 0, name: "Activewear" }, { weight: 0, name: "Disney Project" }, { weight: 0, name: "Dresses and Jumpsuits" }, { weight: 0, name: "Fleece" }, { weight: 0, name: "HEATTECH Collection" }, { weight: 0, name: "Ines de la Fressange" }, { weight: 0, name: "Intimates" }, { weight: 0, name: "Jeans" }, { weight: 0, name: "Loungewear" }, { weight: 0, name: "Outerwear and Blazers" }, { weight: 0, name: "Pants" }, { weight: 0, name: "Shirts and Blouses" }, { weight: 0, name: "Skirts" }, { weight: 0, name: "Socks and Hosiery" }, { weight: 0, name: "Sweaters" }, { weight: 0, name: "Sweatshirts and Sweatpants" }, { weight: 0, name: "T-Shirts and Tops" }, { weight: 0, name: "UT: Graphic Tees" }, { weight: 0, name: "Wear To Work" }, { weight: 0, name: "Mix and Match" }];
// temporary array holds objects with position and sort-value
var mapped = data.map(function (el, i) {
        return {
            index: i, 
            value: el.weight
        };
    });
// sorting the mapped array containing the reduced values
mapped.sort(function (a, b) {
    return a.value - b.value || a.index - b.index;
});
// container for the resulting order
var result = mapped.map(function (el) {
    return data[el.index];
});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }

最简单的解决方案是保存位置,然后在对象相等的情况下进行比较:

var sortData = data.slice(0);
sortData.forEach(function(element, index){
    element.index = index;
});
sortData.sort(function(a,b) {
    var diff = a.weight - b.weight;
    return diff === 0 ? a.index - b.index : diff;
});
sortData.forEach(function(element){
    delete element.index;
});

您要查找的是排序算法stability的一个属性。这意味着等值元素的顺序在排序后保持不变。不同的浏览器使用不同的排序算法,有些浏览器使用稳定的算法,有些则使用不稳定的算法。您可以在这个SO线程上看到浏览器之间的差异:https://stackoverflow.com/a/3027715/1641070.

正如您在Ramda源代码中看到的,它使用内置的排序机制,所以如果您使用Ramda,您将得到相同的结果:https://github.com/ramda/ramda/blob/v0.22.1/src/sortBy.js#L38:L42

您可以使用下划线的_.sortBy(data,'weight')进行稳定排序。检查