根据MDN规范,Javascript的sort()函数是“不稳定的”(对于相同元素不保持输入顺序)。
具有讽刺意味的是,似乎Firefox目前没有实现这一点,但Chrome似乎已经实现了。
这让我有点问题。我有一组要排序的元素 - 一旦排序,我想将它们标记为“已排序”,以便后续的排序尝试不会浪费很多时间发现它们已经排序了(如果有任何变化,我可以取消标记)。
问题是,我的解决方案在我的比较函数中返回“0”,但这意味着我只是为每个元素返回“等价”,它们可以(并且将)被洗牌。
这演示了问题(fiddle here)。
在Chrome上运行,您会发现集合的中间元素在后续排序中移动 - 在Mozilla上不会发生这种情况(至少我这里的版本不会)。
有什么办法可以避免每次都要重新排序吗?实际排序更加复杂,并且需要检查数百个元素,所以需要很长时间,我不想重复不必要的工作。
编辑后添加:我甚至尝试使用数组索引来强制按顺序对数组进行排序,但即使在Chrome上也不起作用。Chrome似乎使用了Quicksort的变体,'just for the hell of it'交换数组中的元素。
看来我只能每次重新排序,跳过排序或者实现自己的算法...
具有讽刺意味的是,似乎Firefox目前没有实现这一点,但Chrome似乎已经实现了。
这让我有点问题。我有一组要排序的元素 - 一旦排序,我想将它们标记为“已排序”,以便后续的排序尝试不会浪费很多时间发现它们已经排序了(如果有任何变化,我可以取消标记)。
问题是,我的解决方案在我的比较函数中返回“0”,但这意味着我只是为每个元素返回“等价”,它们可以(并且将)被洗牌。
这演示了问题(fiddle here)。
<head>
<script>
var firsttime=true;
function test() {
debugger;
var elements = document.getElementById('test').children;
var sortMe = [];
for (var i=0; i<elements.length; i++)
sortMe.push(elements[i]);
sortMe.sort(function(a, b) {
if (firsttime) {
if (a.innerText < b.innerText) return -1;
else if (a.innerText > b.innerText) return 1;
else return 0;
} else {
return 0;
}
});
var parent = document.getElementById('test');
parent.innerHTML = "";
for(var i = 0, l = sortMe.length; i < l; i++) {
parent.appendChild(sortMe[i]);
}
firsttime=false;
}
</script>
</head>
<body>
<div id=test>
<div>B</div>
<div>D</div>
<div>A</div>
<div>C</div>
<div>E</div>
<div>B</div>
<div>D</div>
<div>A</div>
<div>C</div>
<div>E</div>
<div>B</div>
<div>D</div>
<div>A</div>
<div>C</div>
<div>E</div>
</div>
<input type=button onclick=test()>
</body>
在Chrome上运行,您会发现集合的中间元素在后续排序中移动 - 在Mozilla上不会发生这种情况(至少我这里的版本不会)。
有什么办法可以避免每次都要重新排序吗?实际排序更加复杂,并且需要检查数百个元素,所以需要很长时间,我不想重复不必要的工作。
编辑后添加:我甚至尝试使用数组索引来强制按顺序对数组进行排序,但即使在Chrome上也不起作用。Chrome似乎使用了Quicksort的变体,'just for the hell of it'交换数组中的元素。
看来我只能每次重新排序,跳过排序或者实现自己的算法...
sort
函数(当不适合使用不稳定排序时)。你可以使用自己的稳定排序算法(实现广泛可用)。 - Greg Hewgill