JavaScript[].Sort()方法在应该保留元素时进行排序

JavaScript [ ].sort( ) method sorts when it should leave elements alone

本文关键字:元素 保留 排序 Sort 方法 JavaScript      更新时间:2023-09-26

我有一个JavaScript对象数组。我想用一个特定的度规来排序。在特殊情况下,度规每次都有相同的值。下面是一个示例数组:

var myArray = [{"key":400686,"metric":999999},{"key":52601288,"metric":999999},{"key":1380180030,"metric":999999},{"key":909661,"metric":999999},{"key":401336,"metric":999999},{"key":1317275,"metric":999999},{"key":8642696,"metric":999999},{"key":1374360020,"metric":999999},{"key":602871933,"metric":999999},{"key":410174,"metric":999999},{"key":503411,"metric":999999},{"key":401511,"metric":999999},{"key":410196,"metric":999999},{"key":419377,"metric":999999},{"key":429167,"metric":999999},{"key":609656,"metric":999999},{"key":837941,"metric":999999},{"key":2410791,"metric":999999},{"key":4501004,"metric":999999},{"key":8633371,"metric":999999},{"key":1356540155,"metric":999999},{"key":1374360757,"metric":999999}];

当我做这样简单的调用时:

myArray.sort( function( a, b ){ return 0; } );

数组被排序了!显然,它应该保持不变,因为排序函数中的返回值为0表示相等。

还有其他人遇到过这个问题吗?

0表示相等,这意味着元素是可互换的。这并不意味着它们不会被移动。这意味着它们可以自由交换或保持在原来的位置,数组仍然会被排序。

这是因为排序是不稳定的,它不一定保持相等项的相对顺序。

您可以使用稳定的排序算法,如归并排序。

如果您希望将相同的元素按可预测的顺序排序,那么您需要一个辅助键来识别哪些相同的元素应该在其他元素之前。在您的示例数组中,您可以使用如下的自定义排序函数,该函数将首先按度量排序,如果它们相同,则按键排序:

myArray.sort( function( a, b ){ 
    if (a.metric != b.metric) {
        return(b.metric - a.metric);
    }
    // when metrics are the same, sort by key as secondary sort
    return(b.key - a.key)
});

或者,如果您希望保留相同元素的现有顺序,那么您需要在每次排序之前快速传递以添加顺序值:

// mark each value with it's current position in the array
for (var i = 0; i < myArray.length; i++) {
    myArray[i].sortIndexForTies = i;
}
myArray.sort( function( a, b ){ 
    if (a.metric != b.metric) {
        return(b.metric - a.metric);
    }
    // when metrics are the same, sort by the original array position as second sort key
    return(b.sortIndexForTies - a.sortIndexForTies)
});

我发现了一个很好的解决方法,我通过在排序参数上添加一个delta来使排序偏离我所关心的精度。偏差使数组倾向于保持相同的顺序。如果在距离上有一个单位的差异(我的精度是在15位),该元素将被正确排序。

for( var i = 0, len = myArray.length, delta = 0; i < len; i++, delta += 0.000001 )
{
  myArray[ i ].metric -= delta;
}
function byMetric( a, b )
{
  return b.metric - a.metric;
}
myArray.sort( byMetric );