Close-up of hands shuffling a deck of cards

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 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.