Javascript 为什么要使用<;对JS数字数组进行排序;工作
在JavaScript中对数字数组进行排序时,我意外地使用了Javascript 为什么要使用<;对JS数字数组进行排序;工作,javascript,Javascript,在JavaScript中对数字数组进行排序时,我意外地使用了,具体取决于sort()实现,很可能它从未检查-1。它更简单、更快,而且没有任何区别(因为无论如何,分类都不能保证是稳定的,IIRC) 如果内部执行的检查sort()为compareFunction(a,b)>0,则实际上true被解释为a>b,false被解释为a比较true覆盖为1,而false覆盖为0 注意:这都是猜测和猜测,我还没有通过实验或在浏览器源代码中证实这一点,但它很可能是正确的。如果我们分析所做的事情,这似乎大部分是运
,具体取决于sort()
实现,很可能它从未检查-1
。它更简单、更快,而且没有任何区别(因为无论如何,分类都不能保证是稳定的,IIRC)
如果内部执行的检查sort()
为compareFunction(a,b)>0
,则实际上true
被解释为a>b
,false
被解释为a
比较true
覆盖为1,而false
覆盖为0
注意:这都是猜测和猜测,我还没有通过实验或在浏览器源代码中证实这一点,但它很可能是正确的。如果我们分析所做的事情,这似乎大部分是运气,因为在这种情况下,3和2被认为是“相同”的,应该是可互换的。我假设在这种情况下,JS引擎对任何被认为相等的值都保持原始顺序:
设a=[1,3,2,4];
a、 排序((n1,n2)=>{
常数结果=n10){
log(${n2}在${n1}之前);
}否则{
log(${n1}与${n2}位于同一位置);
}
返回结果;
})
控制台日志(a)
由于其较小的尺寸以及Chrome V8(可能还有其他浏览器)中当前实现的排序,这种排序可以在您的输入阵列上工作
比较器函数的返回值定义在:
- 如果
compareFunction(a,b)
小于0,则将a
排序为小于0的索引
b
,即a
排在第一位李>
- 如果
compareFunction(a,b)
返回0,则保留a
和
b
彼此之间没有变化,但对所有对象进行排序
不同的元素
- 如果
compareFunction(a,b)
大于0,则将b
排序到低于a
的索引,即b
排在第一位
但是,您的函数返回二进制true
或false
,与数字相比,其计算结果分别为1
或0
。这有效地将n1
中的比较与n1===n2
合并,声称两者是相等的。如果n1
为9且n2
为3,9<3==false
或0
。换句话说,排序时9和3“彼此保持不变”,而不是坚持“将9排序到低于3的索引”
如果您的数组小于11个元素,则Chrome V8的排序例程将显示为,并且不执行任何步骤:
但是,在选择轴心点和分区时,依赖于所有三种比较:
var order = comparefn(element, pivot);
if (order < 0) {
// ...
} else if (order > 0) {
// ...
}
// move on to the next iteration of the partition loop
var order=comparefn(元素,轴);
如果(顺序<0){
// ...
}否则,如果(订单>0){
// ...
}
//继续进行分区循环的下一次迭代
这保证了对数组(如[1,3,2,4]
)的准确排序,并至少会将包含10个以上元素的数组置于一个几乎肯定不准确的快速排序步骤中
更新7/19/19:由于在本回答中讨论了V8(6)的版本,V8的数组排序的实现移到了7.0中,如本文所讨论的,插入排序在的数组上调用
上面链接的文章描述了问题发生时V8排序的历史情况:
Array.prototype.sort
和TypedArray.prototype.sort
依赖于用JavaScript编写的相同快速排序实现。排序算法本身相当简单:其基础是快速排序,对于较短的数组(长度<10),插入排序可回退。当快速排序递归达到子数组长度10时,也会使用插入排序回退。对于较小的数组,插入排序更有效。这是因为快速排序在分区后会被递归调用两次。每个递归调用都有创建(和丢弃)堆栈帧的开销
无论实现细节有何变化,如果排序比较器遵守标准,代码将按预期排序,但如果比较器未履行合同,则所有赌注都将取消。需要一个返回数字(负、零或正)的比较器
假设您在V8引擎(Node.js、Chrome等)上运行,您会发现返回值与0比较(yourrurnvalue>0
)。在这种情况下,返回值被转换为一个数字,因此:
- Truthy值转换为1
- Falsy值将转换为0
因此,基于文档和上述内容,您的函数将在特定情况下以降序返回排序数组,但在其他情况下可能会停止,因为不考虑-1值。在我最初的评论之后,我想知道查找此排序方法失败的数组有多容易
我对长度不超过8的数组(在数组大小的字母表上)进行了彻底的搜索,但没有找到任何结果。由于我的算法开始太慢了,我把它改成了大小为2的字母表,发现长度为10的二进制数组都能正确排序。但是,对于长度为11的二进制数组,许多数组的排序不正确,例如[0,1,1,1,1,1,1,1,0]
// Check if 'array' is properly sorted using the "<" comparator function
function sortWorks(array) {
let sorted_array = array.sort(function(n1, n2) {
return n1 < n2;
});
for (let i=0; i<sorted_array.length-1; i++) {
if (sorted_array[i] < sorted_array[i+1]) return false;
}
return true;
}
// Get a list of all arrays of length 'count' on an alphabet of size 'max_n'.
// I know it's awful, don't yell at me :'(
var arraysGenerator;
arraysGenerator = function (max_n, count) {
if (count === 0) return [[]];
let arrays = arraysGenerator(max_n, count-1);
let result = [];
for (let array of arrays) {
for (let i = 0; i<max_n; i++) {
result.push([i].concat(array));
}
}
return result;
}
// Check if there are binary arrays of size k which are improperly sorted,
// and if so, log them
function testArraysOfSize(k) {
let arrays = arraysGenerator(2, k);
for (let array of arrays) {
if (!sortWorks(array)) {
console.log(array);
}
}
}
//使用“您可以通过查看返回值的数值来检查数组”是否正确排序。注意返回值0
具有跨浏览器含义。@usr2564301return n2-n1
一个不起作用的示例的可能重复项是[1,2,1,2,1,2,1,2,1,2]
。我不知道简短的示例是否会失败。@Nic
// Insertion sort is faster for short arrays.
if (to - from <= 10) {
InsertionSort(a, from, to);
return;
}
var order = comparefn(tmp, element);
if (order > 0) {
a[j + 1] = tmp;
} else {
break;
}
var order = comparefn(element, pivot);
if (order < 0) {
// ...
} else if (order > 0) {
// ...
}
// move on to the next iteration of the partition loop
// Check if 'array' is properly sorted using the "<" comparator function
function sortWorks(array) {
let sorted_array = array.sort(function(n1, n2) {
return n1 < n2;
});
for (let i=0; i<sorted_array.length-1; i++) {
if (sorted_array[i] < sorted_array[i+1]) return false;
}
return true;
}
// Get a list of all arrays of length 'count' on an alphabet of size 'max_n'.
// I know it's awful, don't yell at me :'(
var arraysGenerator;
arraysGenerator = function (max_n, count) {
if (count === 0) return [[]];
let arrays = arraysGenerator(max_n, count-1);
let result = [];
for (let array of arrays) {
for (let i = 0; i<max_n; i++) {
result.push([i].concat(array));
}
}
return result;
}
// Check if there are binary arrays of size k which are improperly sorted,
// and if so, log them
function testArraysOfSize(k) {
let arrays = arraysGenerator(2, k);
for (let array of arrays) {
if (!sortWorks(array)) {
console.log(array);
}
}
}