Javascript Array.sort()方法在不同浏览器中的稳定性如何?

Javascript Array.sort()方法在不同浏览器中的稳定性如何?,javascript,arrays,sorting,cross-browser,stable-sort,Javascript,Arrays,Sorting,Cross Browser,Stable Sort,我知道ECMA脚本规范没有指定用于排序数组的算法,也没有指定排序是否应该是稳定的 我发现了firefox使用稳定排序的原因 有人知道IE 6/7/8、Chrome和Safari吗?如果你正在寻找一个应该使用非本机排序算法的浏览器列表,我的建议是不要 相反,在脚本加载时执行排序健全性检查,并据此做出决定 由于该规范在这方面不需要特定的行为,因此它不能避免以后的更改,即使在同一浏览器行中也是如此 您可以提交一个补丁,将这些测试包含在他们的套件中。但同样,特征检测优于浏览器检测 我想分享一个我在C/C

我知道ECMA脚本规范没有指定用于排序数组的算法,也没有指定排序是否应该是稳定的

我发现了firefox使用稳定排序的原因


有人知道IE 6/7/8、Chrome和Safari吗?

如果你正在寻找一个应该使用非本机排序算法的浏览器列表,我的建议是不要

相反,在脚本加载时执行排序健全性检查,并据此做出决定

由于该规范在这方面不需要特定的行为,因此它不能避免以后的更改,即使在同一浏览器行中也是如此


您可以提交一个补丁,将这些测试包含在他们的套件中。但同样,特征检测优于浏览器检测

我想分享一个我在C/C++中经常使用的技巧,用于
qsort()

JS'sort()允许指定比较函数。创建第二个长度相同的数组,并用从0开始递增的数字填充它

function stableSorted(array, compareFunction) {
  compareFunction = compareFunction || defaultCompare;
  var indicies = new Array(array.length);
  for (var i = 0; i < indicies.length; i++)
    indicies[i] = i;
它将从第二个数组中获取两个元素:将它们用作原始数组的索引并比较元素

    var aValue = array[a], bValue = array[b];
    var order = compareFunction(a, b);
    if (order != 0)
      return order;
如果元素恰好相等,则比较它们的索引以使顺序稳定

   if (a < b)
     return -1;
   else
     return 1;
  });
if(a
在sort()之后,第二个数组将包含索引,您可以使用这些索引以稳定的排序顺序访问原始数组的元素

  var sorted = new Array(array.length);
  for (var i = 0; i < sorted.length; i++)
    sorted[i] = array[indicies[i]];
  return sorted;
}

// The default comparison logic used by Array.sort(), if compareFunction is not provided:
function defaultCompare(a, b) {
  a = String(a);
  b = String(b);
  if (a < b) return -1;
  else if (a > b) return 1;
  else return 0;
}
var sorted=新数组(Array.length);
对于(变量i=0;ib)返回1;
否则返回0;
}
一般来说,稳定的排序算法只是在不断成熟,与良好的ol'qsort相比,它仍然需要更多的额外内存。我想这就是为什么很少有规范要求稳定排序。

从ES2019开始,要求稳定排序。在ECMAScript第一版到ES2018中,它被允许是不稳定的

(忽略标题,如果引擎排序稳定,则第二组数字应按顺序排列)。注意:这个测试用例不适用于Chrome的某些版本(从技术上讲,是V8),Chrome根据数组的大小切换排序算法,对小数组使用稳定排序,而对大数组使用不稳定排序。(.)请参阅问题的结尾,了解修改后的版本,该版本使数组足够大,可以触发行为

IE的分类自从我使用它以来一直是稳定的(所以IE6)。在IE8中再次检查,情况似乎仍然如此

尽管你链接到的Mozilla页面上说Firefox的排序是稳定的,但我肯定地说,Firefox2.0之前(包括Firefox2.0)并不总是如此

一些粗略的结果:

  • IE6+:稳定
  • Firefox<3:不稳定
  • Firefox>=3:稳定
  • 铬<70:不稳定
  • 铬>=70:稳定
  • Opera<10:不稳定
  • Opera>=10:稳定
  • Safari 4:稳定
  • 边缘:对于长数组()不稳定
Windows上的所有测试

另请参见:

这个测试用例(修改自)将通过确保数组有足够的条目来选择“更高效”的排序方法来演示V8中的问题(例如,NodeV6,Chrome
函数对(\ux,\uy){
this.x=x;
this.y=\u y;
}
功能配对排序(a、b){
返回a.x-b.x;
}
var y=0;
var检查=[];
同时(检查长度<100){
检查.推(新的一对(数学地板(数学随机()*3)+1,++y));
}
检查、排序(pairSort);
var min={};
var=0;
对于(变量i=0;ientry.y){
log(“在“+found.i+”:“+found.y+”>“+entry.y”处不稳定);
++问题;
}
}否则{
min[entry.x]={x:entry.x,y:entry.y,i:i};
}
}
如果(!问题){
log(“排序似乎稳定”);

}
从V8 v7.0和Chrome 70开始,我们的
Array.prototype.sort
实现现在是稳定的 如果有人认为它有用,我有一个polyfill,我现在正在删除它:

const stable=(count=>{
常数
数组=新数组(计数),
桶={};
让我,k,v;
对于(i=0;ia[0]-b[0]);
对于(i=0;iv){
返回false;
}
桶[k]=v;
}
返回true;
//Edge的JS引擎在变得不稳定之前有一个512的阈值,所以使用一个超出该阈值的数字:
})(600);
如果(!稳定){
常数
{prototype}=数组,
{sort}=原型;
Object.defineProperty(原型“sort”{
对,,
值(sortFn){
常数
数组=这个,
len=数组长度,
temp=新阵列(len);
让我;
对于(i=len;i-->0;/*空*/){
温度[i]=i;
}
sortFn=sortFn | | defaultSort;
sort.call(temp,(index1,index2)=>sortFn(数组[index1],数组[index2])| | index1-index2);
//我们不能直接在数组中执行此操作,因为我们可能会在将元素放入数组之前覆盖它
//正确地点:
对于(i=len;i-->0;/*空*/){
temp[i]=数组[temp[i]];
}
for(i=len;
  var sorted = new Array(array.length);
  for (var i = 0; i < sorted.length; i++)
    sorted[i] = array[indicies[i]];
  return sorted;
}

// The default comparison logic used by Array.sort(), if compareFunction is not provided:
function defaultCompare(a, b) {
  a = String(a);
  b = String(b);
  if (a < b) return -1;
  else if (a > b) return 1;
  else return 0;
}