I got this piece of code from a website for randomizing a list of items. [This is for a music player that randomizes the songs (list) in every new visit by the user, thus not boring them by starting with the same song that they heard in the past visit]
$(document).ready(function(){
$('ul').each(function(){
// get current ul
var $ul = $(this);
// get array of list items in current ul
var $liArr = $ul.children('li');
// sort array of list items in current ul randomly
$liArr.sort(function(a,b){
// Get a random number between 0 and 10
var temp = parseInt( Math.random()*10 );
// Get 1 or 0, whether temp is odd or even
var isOddOrEven = temp%2;
// Get +1 or -1, whether temp greater or smaller than 5
var isPosOrNeg = temp>5 ? 1 : -1;
// Return -1, 0, or +1
return( isOddOrEven*isPosOrNeg );
})
// append list items to ul
.appendTo($ul);
});
});
This works perfectly fine when I open my site in Chrome browser. The sorting is done pretty heavily and hence I could see that the list is randomized to a great extent.
But in Firefox and IE, the sorting is not happening to a good extent. I see that the first list item remains first in 7 out of 10 tries. And I could see the same for many other items. Ex: Item #5 occur in 3rd position in 5 out of 10 tries. With these observations, I could tell that the JS code is not working properly in IE and Firefox. (may be due to the way different browsers treat JS code because of the differences in the engine)
Now, Is there anything I can change in the JS code to make it work in all browsers?
Or Is there any other better sorting algorithm that would do a decent sorting in all browsers when implemented using JS?
I understand that a part of my 2nd question has been answered in other questions within SE but I couldn’t find about the ‘browser compatibility’ part in those questions.
Thanks for helping.
Your randomisation is not very good:
That means in a half of the cases you return
0, which tells the sort function that the two items are equal. A good sort function will notice that and not ask again. With only a few items, you have a very high chance of the items not getting sorted well. You can proof this by counting (logging) how often your compare-function is called.Also you don’t need to return only
+1,0or-1, you can just return any positive or negative number (see also below). For randomizing, you never really need to return equality. So, use this instead:However, one should not use
sortfor randomisation at all.Math.randomdoes not lead to a total ordering, and sort is not made for that: (from the EcmaScript specification)An optimised sort function can easily screw up if these properties are not fulfilled. That can mean no sorting at all as well as never terminating sorting. See Is it correct to use JavaScript Array.sort() method for shuffling?
Instead, use a standard shuffle algorithm, there are many good ones. The Fisher-Yates-Shuffle is really simple to implement for example, see the question How to randomize (shuffle) a JavaScript array?.