简体   繁体   English

Array.sort在IOS中得到不同的结果

[英]Array.sort get different result in IOS

it's a simple code, but returns different results in Andriod and Iphone. 这是一个简单的代码,但在Andriod和Iphone中返回不同的结果。

var str = [1,2,3,4,5].sort(function () {
    return -1;
})
document.write(str);

In MDN( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort ) it says 在MDN( https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort )中,它说

  • If compareFunction(a, b) is less than 0, sort a to a lower index than b, ie a comes first. 如果compareFunction(a,b)小于0,则将a排序为低于b的索引,即a先来。
  • If compareFunction(a, b) returns 0, leave a and b unchanged with respect to each other, but sorted with respect to all different elements. 如果compareFunction(a,b)返回0,则保持a和b相对于彼此保持不变,但是对于所有不同的元素进行排序。 Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (eg Mozilla versions dating back to at least 2003) respect this. 注意:ECMAscript标准不保证这种行为,因此并非所有浏览器(例如可追溯到至少2003年的Mozilla版本)都尊重这一点。
  • If compareFunction(a, b) is greater than 0, sort b to a lower index than a. 如果compareFunction(a,b)大于0,则将b排序为低于a的索引。 compareFunction(a, b) must always return the same value when given a specific pair of elements a and b as its two arguments. 当给定一对特定元素a和b作为其两个参数时,compareFunction(a,b)必须始终返回相同的值。 If inconsistent results are returned then the sort order is undefined. 如果返回不一致的结果,则排序顺序未定义。

So the result should be 1,2,3,4,5. 所以结果应该是1,2,3,4,5。 But is Iphone it shows 5,4,3,2,1 但它是Iphone它显示5,4,3,2,1

Here is a link for you to try this code. 这是您尝试此代码的链接。 http://www.madcoder.cn/demos/ios-test.html http://www.madcoder.cn/demos/ios-test.html

And after I did more and more test. 在我做了越来越多的测试之后。 I found Iphone is doing a different sorting. 我发现Iphone正在进行不同的排序。 Here is a link shows how sort works: http://www.madcoder.cn/demos/ios-test2.html 这是一个显示排序如何工作的链接: http//www.madcoder.cn/demos/ios-test2.html

The javascript engines use different algorithms for their sort function. javascript引擎使用不同的算法进行排序功能。 Since the compare function doesn't compare values, you get the result of the inner workings of the different algorithms instead of having a sorted result. 由于compare函数不比较值,因此您可以获得不同算法的内部工作结果,而不是具有排序结果。

Looking at the source code of V8 engine (Chrome) and JavaScriptCore (which seems to be used by Safari, or at least the sort function gives the same result, so I guess it uses the same kind of algorithm), you can view the functions that are being used. 查看V8引擎(Chrome)和JavaScriptCore的源代码(似乎是Safari使用的,或者至少sort函数给出相同的结果,所以我猜它使用相同类型的算法),你可以查看函数正在使用。

Not that it might not be exactly the functions used, what's important is that the algorithms are different. 并不是说它可能不是所使用的功能,重要的是算法是不同的。 They give the same result if you actually compare values, but if not, the result is dependent on the way they operate, not on the function itself. 如果您实际比较值,它们会给出相同的结果,但如果不是,则结果取决于它们的运行方式,而不是函数本身。 At least not completely. 至少不完全。

Here's V8 engine sorting function. 这是V8发动机分拣功能。 You'll see that for arrays bigger than 10 elements, the algorithm isn't the same, so the result for arrays smaller than 10 elements is different than for those bigger than 10 elements. 您会看到,对于大于10个元素的数组,算法不一样,因此小于10个元素的数组的结果与大于10个元素的数组的结果不同。

You can find following algorithms here: https://code.google.com/p/chromium/codesearch#chromium/src/v8/src/js/array.js&q=array&sq=package:chromium&dr=C 您可以在此处找到以下算法: https//code.google.com/p/chromium/codesearch#chromium/src/v8/src/js/array.js&q=array&sq=package : chromium&dr=C

 comparefn = function(a, b) { return -1 } var InsertionSort = function InsertionSort(a, from, to) { for (var i = from + 1; i < to; i++) { var element = a[i]; for (var j = i - 1; j >= from; j--) { var tmp = a[j]; var order = comparefn(tmp, element); if (order > 0) { a[j + 1] = tmp; } else { break; } } a[j + 1] = element; } console.log(a); } var GetThirdIndex = function(a, from, to) { var t_array = new InternalArray(); // Use both 'from' and 'to' to determine the pivot candidates. var increment = 200 + ((to - from) & 15); var j = 0; from += 1; to -= 1; for (var i = from; i < to; i += increment) { t_array[j] = [i, a[i]]; j++; } t_array.sort(function(a, b) { return comparefn(a[1], b[1]); }); var third_index = t_array[t_array.length >> 1][0]; return third_index; } var QuickSort = function QuickSort(a, from, to) { var third_index = 0; while (true) { // Insertion sort is faster for short arrays. if (to - from <= 10) { InsertionSort(a, from, to); return; } if (to - from > 1000) { third_index = GetThirdIndex(a, from, to); } else { third_index = from + ((to - from) >> 1); } // Find a pivot as the median of first, last and middle element. var v0 = a[from]; var v1 = a[to - 1]; var v2 = a[third_index]; var c01 = comparefn(v0, v1); if (c01 > 0) { // v1 < v0, so swap them. var tmp = v0; v0 = v1; v1 = tmp; } // v0 <= v1. var c02 = comparefn(v0, v2); if (c02 >= 0) { // v2 <= v0 <= v1. var tmp = v0; v0 = v2; v2 = v1; v1 = tmp; } else { // v0 <= v1 && v0 < v2 var c12 = comparefn(v1, v2); if (c12 > 0) { // v0 <= v2 < v1 var tmp = v1; v1 = v2; v2 = tmp; } } // v0 <= v1 <= v2 a[from] = v0; a[to - 1] = v2; var pivot = v1; var low_end = from + 1; // Upper bound of elements lower than pivot. var high_start = to - 1; // Lower bound of elements greater than pivot. a[third_index] = a[low_end]; a[low_end] = pivot; // From low_end to i are elements equal to pivot. // From i to high_start are elements that haven't been compared yet. partition: for (var i = low_end + 1; i < high_start; i++) { var element = a[i]; var order = comparefn(element, pivot); if (order < 0) { a[i] = a[low_end]; a[low_end] = element; low_end++; } else if (order > 0) { do { high_start--; if (high_start == i) break partition; var top_elem = a[high_start]; order = comparefn(top_elem, pivot); } while (order > 0); a[i] = a[high_start]; a[high_start] = element; if (order < 0) { element = a[i]; a[i] = a[low_end]; a[low_end] = element; low_end++; } } } if (to - high_start < low_end - from) { QuickSort(a, high_start, to); to = low_end; } else { QuickSort(a, from, low_end); from = high_start; } } }; InsertionSort([1, 2, 3, 4, 5], 0, 5); //QuickSort is recursive and calls Insertion sort, so you'll have multiple logs for this one QuickSort([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13], 0, 13); //You'll see that for arrays bigger than 10, QuickSort is called. var srt = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13].sort(function() { return -1 }) console.log(srt) 

And JavaScriptCore uses merge sort. JavaScriptCore使用合并排序。 You can find this algorithm here: http://trac.webkit.org/browser/trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js 你可以在这里找到这个算法: http//trac.webkit.org/browser/trunk/Source/JavaScriptCore/builtins/ArrayPrototype.js

 function min(a, b) { return a < b ? a : b; } function merge(dst, src, srcIndex, srcEnd, width, comparator) { var left = srcIndex; var leftEnd = min(left + width, srcEnd); var right = leftEnd; var rightEnd = min(right + width, srcEnd); for (var dstIndex = left; dstIndex < rightEnd; ++dstIndex) { if (right < rightEnd) { if (left >= leftEnd || comparator(src[right], src[left]) < 0) { dst[dstIndex] = src[right++]; continue; } } dst[dstIndex] = src[left++]; } } function mergeSort(array, valueCount, comparator) { var buffer = []; buffer.length = valueCount; var dst = buffer; var src = array; for (var width = 1; width < valueCount; width *= 2) { for (var srcIndex = 0; srcIndex < valueCount; srcIndex += 2 * width) merge(dst, src, srcIndex, valueCount, width, comparator); var tmp = src; src = dst; dst = tmp; } if (src != array) { for (var i = 0; i < valueCount; i++) array[i] = src[i]; } return array; } console.log(mergeSort([1, 2, 3, 4, 5], 5, function() { return -1; })) 

Again these may not be exactly the functions used in each browser, but it shows you how different algorithms will behave if you don't actually compare values. 同样,这些可能并不完全是每个浏览器中使用的函数,但它会向您展示如果您实际上不比较值,不同算法的行为方式。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM