It’s been said that there are only two hard problems in computer science: cache invalidation and naming things. To those, I might add a third: reordering and prioritizing things. Thankfully, a lot of brainpower has been expended on solving just those kinds of problems.
Shuffling and sorting is often needed in scripts: ranking a series of recorded scores, for example, or randomly reordering values for use in a game. Unfortunately JavaScript doesn’t yet have a built-in shuffle
method, and it’s sort
method has a few quirks… but both can be accomplished if you know how.
Shuffling An Array
I covered shuffling previously in my article on recipes for randomness in JavaScript: this version, known as the Durstenfeld shuffle, is a high-performance variation:
function shuffle(array) {
for (var i = array.length - 1; i > 0; i--) {
var j = Math.floor(Math.random() * (i + 1));
var temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
Given an array:
var flintstones = ["Pebbles", "Bam-Bam", "Wilma", "Fred"];
We can shuffle it with:
shuffle(flintstones);
Which might produce (in the console) something like:
> ["Wilma", "Bam-Bam", "Fred", "Pebbles"]
The result will always be randomly shuffled.
Sorting an Array
You can use the sort
method to sort an array:
flintstones.sort();
…which will arrange the array elements in alphabetical order:
> ["Bam-Bam", "Fred", "Pebbles", "Wilma"]
However, things get tricky if we try to sort numerical information:
var ranValues = [ 7, 11, 12, 15, 3, 1, 10 ];
Sorting the array yields this rather confusing result:
> [1, 10, 11, 12, 15, 3, 7]
What’s going on?
By default, sort
works in lexicographical order: i.e. a dictionary sort. This includes numerals: sort
converts the numbers in the array to strings, then orders them to produce a result. In that system 3
comes immediately before 30
, yielding the strange result we see above.
Fortunately, we can pass a function into the sort
method to control the sorting process. To sort numerals correctly use:
sort(function(a,b){return a - b})
This function takes two values from the array, a
and b
. It will only return one of three values: -1
means that a
is less than b
, and should be placed before it; 0
means that the values are equal, and no change should be applied, and 1
means that a
should be placed after b
. Applied to our array example produces the correct, expected result:
ranValues.sort(function(a,b){return a - b});
> [1, 3, 7, 10, 11, 12, 15]
To produce a descending sort, reverse the position of a
and b
in the function:
ranValues.sort(function(a,b){return b - a});
> [15, 12, 11, 10, 7, 3, 1]
Photograph by Christian Dalager, used under a Creative Commons Attribution-NonCommercial 2.0 Generic license
Enjoy this piece? I invite you to follow me at twitter.com/dudleystorey to learn more.