JavaScript[].Sort()方法在应该保留元素时进行排序
JavaScript [ ].sort( ) method sorts when it should leave elements alone
我有一个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 );
相关文章:
- Jquery html() 和保留元素名称
- 单击其他元素或鼠标向上时隐藏输入框,但保留一次焦点
- 如何在页面刷新后保留动态创建的html元素及其数据/值
- 在正文中保留附加的相对元素
- 将所有元素保留在同一位置
- 如何添加动态表单元素但保留其值(JS)
- 从数组中删除元素,然后保留其状态以备将来使用,而不使用全局变量
- 单击按钮后如何保留元素
- 使用链接截断html中的文本以显示更多/更少并将元素保留在里面
- AngularJS 1.2.0 $http不保留数组元素
- 在开发元素被确认后,在开发元素下方保留一个单击按钮
- 在谷歌修饰的前元素中保留 html 字符
- 保留列表中移动元素的顺序
- 如何将附加的元素保留在父元素中
- 如何计算坐标以将元素保留在用户屏幕的区域中
- 当浏览器调整大小时,将元素保留在父视图中
- 为动态更改的元素保留事件
- 将DOM元素保留在页面上还是根据需要重新呈现它们更有效
- 重新添加的画布元素保留内容
- 如何在jQuery移除时将奇数/偶数元素保留在左侧或右侧