用JavaScript排序:每個比較函數都應該有一個“返回0”語句嗎?

[英]Sorting in JavaScript: Should every compare function have a “return 0” statement?


I recently read many answers about sorting in JavaScript and I often stumble upon a compare function that looks like this:

我最近閱讀了許多關於JavaScript排序的答案,我經常偶然發現一個比較函數,如下所示:

array.sort(function(a,b){ a > b ? 1 : -1; });

So it is a compare function that returns 1 if a is greater than b and -1 if a is less than OR EQUAL TO b. As described on MDN (link), a compare function can also return zero, to ensure that the relative position of two items remains unchanged:

所以它是一個比較函數,如果a大於b則返回1,如果a小於OR EQUAL,則返回-1。如MDN(鏈接)所述,比較函數也可以返回零,以確保兩個項目的相對位置保持不變:

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相對於彼此保持不變,但是對於所有不同的元素進行排序。

So the official examples look more like this:

所以官方的例子看起來更像是這樣的:

function compare(a, b) {
  if (a < b) return -1;
  if (a > b) return 1;
  return 0;
}

And indeed, by adding a return 0 statement, the sorting algorithm often needs less iterations and runs faster in total (JSPerf).

實際上,通過添加return 0語句,排序算法通常需要更少的迭代並且總計運行得更快(JSPerf)。

So I was wondering if there is any advantage on omitting a return 0 statement.

所以我想知道在省略return 0語句方面是否有任何優勢。

I realized that on MDN, it also says:

我意識到在MDN上,它還說:

Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.

注意:ECMAscript標准不保證這種行為,因此並非所有瀏覽器(例如可追溯到至少2003年的Mozilla版本)都尊重這一點。

referring to the behavior, that a and b should remain unchanged if 0 is returned. So maybe, by returning 0, we get a slightly different sorted array in different browsers? Could that be a reason? And are there any other good reasons for not returning zero at all?

參考行為,如果返回0,則a和b應保持不變。那么也許,通過返回0,我們在不同的瀏覽器中得到一個稍微不同的排序數組?這可能是個原因嗎?是否有任何其他充分理由不歸零?

2 个解决方案

#1


10  

So I was wondering if there is any advantage on omitting a return 0 statement.

所以我想知道在省略return 0語句方面是否有任何優勢。

Less letters to type. And it might be a tiny bit faster due to the one omitted comparison. All other effects are disadvantages.

輸入更少的字母。由於省略了一個比較,它可能會快一點。所有其他影響都是不利的。

I realized that on MDN, it also says:

我意識到在MDN上,它還說:

Note: the ECMAscript standard does not guarantee this behaviour, and thus not all browsers (e.g. Mozilla versions dating back to at least 2003) respect this.

注意:ECMAscript標准不保證這種行為,因此並非所有瀏覽器(例如可追溯到至少2003年的Mozilla版本)都尊重這一點。

referring to the behavior, that a and b should remain unchanged if 0 is returned.

參考行為,如果返回0,則a和b應保持不變。

That the position of a and b may remain unchanged is only the requirement for a stable sort. This is not a specified behaviour, and some browsers have implemented a non-stable sort algorithm.

a和b的位置可以保持不變只是穩定排序的要求。這不是指定的行為,並且某些瀏覽器實現了非穩定的排序算法。

However, the actual purpose of returning zero is that neither a is sorted before b (as if less than 0) nor that b is sorted before a (as if greater than 0) - basically when a equals b. This is a must-have for a comparison, and all sorting algorithms obey it.

但是,返回零的實際目的是既不是a在b之前排序(如果小於0),也不是b在a之前排序(如果大於0) - 基本上當a等於b時。這是比較的必備條件,所有排序算法都遵循它。

To produce a valid, satisfiable ordering (mathematically: divide the items into totally ordered equivalence classes), a comparison must have certain properties. They are listed in the spec for sort as requirements for a "consistent comparison function".

為了產生有效的,可滿足的排序(數學上:將項划分為完全有序的等價類),比較必須具有某些屬性。它們在規范中列出,作為“一致比較函數”的要求。

The most prominent one is reflexivity, demanding that an item a is equal to a (itself). Another way to say this is:

最突出的是反身性,要求a項等於a(本身)。另一種說法是:

compare(a, a) must always return 0

compare(a,a)必須始終返回0

What happens when a comparison function does not satisfy this (like the one you stumbled upon obviously does)?

當比較函數不滿足時會發生什么(就像你偶然發現的那樣)?

The spec says

規范說

If comparefn […] is not a consistent comparison function for the elements of this array, the behaviour of sort is implementation-defined.

如果comparefn [...]不是此數組元素的一致比較函數,則sort的行為是實現定義的。

which basically means: If you provide an invalid comparison function, the array will probably not be sorted correctly. It might get randomly permuted, or the sort call might not even terminate.

這基本上意味着:如果提供無效的比較函數,則數組可能無法正確排序。它可能會被隨機置換,或者排序調用可能甚至不會終止。

So maybe, by returning 0, we get a slightly different sorted array in different browsers? Could that be a reason?

那么也許,通過返回0,我們在不同的瀏覽器中得到一個稍微不同的排序數組?這可能是個原因嗎?

No, by returning 0 you get a correctly sorted array across browsers (which might be different due to the unstable sort). The reason is that by not returning 0 you get slightly different permuted arrays (if at all), maybe even producing the expected result but usually in a more complicated manner.

不,通過返回0,您可以跨瀏覽器獲得正確排序的數組(由於排序不穩定,可能會有所不同)。原因是,如果不返回0,則會得到稍微不同的置換數組(如果有的話),甚至可能產生預期的結果,但通常是以更復雜的方式。

So what could happen if you don't return 0 for equivalent items? Some implementations have no problems with this, as they never compare an item to itself (even if apparent at multiple positions in the array) - one can optimise this and omit the costly call to the compare function when it is already known that the result must be 0.

那么如果你沒有為同等物品返回0會怎么樣?有些實現沒有問題,因為它們從不將項目與自身進行比較(即使在數組中的多個位置顯而易見) - 可以優化這一點並省略對比較函數的代價高昂的調用,因為已知結果必須是0。

The other extreme would be a never-terminating loop. Assuming you had two equivalent items after each other, you would compare the latter with the former and realise that you had to swap them. Testing again, the latter would still be smaller than the former and you'd have to swap them again. And so on…

另一個極端是永不終止的循環。假設你有兩個相同的項目,你會將后者與前者進行比較,並意識到你必須交換它們。再次測試,后者仍然比前者小,你必須再次交換它們。等等…

However, an efficient algorithm mostly does not test already compared items again, and so usually the implementation will terminate. Still, it might do more or less swaps that actually had been unnecessary, and will therefore take longer than with a consistent comparison function.

但是,一種有效的算法大多數情況下不再測試已經比較的項目,因此通常實現將終止。盡管如此,它可能或多或少地實際上是不必要的掉期,因此比一致的比較功能需要更長的時間。

And are there any other good reasons for not returning zero at all?

是否有任何其他充分理由不歸零?

Being lazy and hoping that the array does not contain duplicates.

懶惰,希望數組不包含重復項。

#2


3  

A compare method should obey the contract

比較方法應遵守合同

Math.sign(compare(a, b)) = -Math.sign(compare(b, a))

If you return a nonzero answer when a==b, that contract is violated.

如果在== b時返回非零答案,則違反該合同。


注意!

本站翻译的文章,版权归属于本站,未经许可禁止转摘,转摘请注明本文地址:https://www.itdaan.com/blog/2014/01/02/72fea0c39d45c362883c806dbd0e711d.html



 
粤ICP备14056181号  © 2014-2021 ITdaan.com