Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sorting an array of more than 10 objects in Chrome

[
{"tag":"fujairah","count":1},
{"tag":"worldwide","count":3},
{"tag":"saudi","count":1},
{"tag":"miami","count":1},
{"tag":"rwo-dealer","count":7},
{"tag":"new york","count":2},
{"tag":"surabaya","count":1},
{"tag":"phillippines","count":1},
{"tag":"vietnam","count":1},
{"tag":"norway","count":1},
{"tag":"x","count":1}
].sort(function(a,b){return a.tag>b.tag})

Sorting an array of 10 objects works fine, once the number of objects exceeds 10, the sort fails in Chrome for Mac. Safari fails at any array size. (Works fine in Firefox)

What is the correct way of sorting arrays of objects by javascript?

like image 433
Johs Avatar asked Apr 15 '14 07:04

Johs


2 Answers

It doesn't matter the number of items, it may be just your case. It's just that's not the correct way to implement a sorting function. You should return 1 (or any positive value, if the first item is "greater" than the second), -1 (or any negative value) or 0 (if the items are equal). Try something like this:

.sort(function(a, b) {
    return a.tag > b.tag ? 1 : (a.tag < b.tag ? -1 : 0);
});

The parentheses around the last ternary operator aren't actually necessary.

like image 74
MaxArt Avatar answered Nov 15 '22 12:11

MaxArt


As noted in the accepted answer the only way to assure the compare function results in expected sort order is to return a number other than 0.

The reasoning for this though is important and should be noted for reference purposes. ECMA standards allow for browser implementations to be unstable. As such there can be no expectation that a function returning 0 will result in the original sort order.

http://www.ecma-international.org/ecma-262/5.1/#sec-15.4.4.11

The sort is not necessarily stable (that is, elements that compare equal do not necessarily remain in their original order). If comparefn is not undefined, it should be a function that accepts two arguments x and y and returns a negative value if x < y, zero if x = y, or a positive value if x > y.

Now for Chrome (and others). Browsers can use whatever sort algorithms they want based on whatever criteria they choose. Since certain algorithms are more efficient based on array size the vendor can choose to change the underlying algo dynamically based on the array size. This is why you're seeing this behavior.

At the time of writing the Chromium source uses length <= 10 as the deciding factor.

https://cs.chromium.org/chromium/src/v8/src/js/array.js?l=707&rcl=9c7cccf55126353a101f194bcf1f8826bc263804

function InnerArraySort(array, length, comparefn) {
  // In-place QuickSort algorithm.
  // For short (length <= 10) arrays, insertion sort is used for efficiency.
  ...
  if (to - from <= 10) {
    InsertionSort(a, from, to);
    return;
  }
 ...
like image 44
andrew.carpenter Avatar answered Nov 15 '22 11:11

andrew.carpenter