Sorting Arrays

From Q
Jump to navigation Jump to search

A JavaScript array has a built-in function called sort. By default, this sorts the objects within the array in ascending numeric or alphabetical order.

var x = [2, 1, 3];
x.sort();
alert(x.toString()); // shows 1, 2, 3

To sort by some other order, you can specify a custom comparison function. The custom comparison function is given two arguments (two objects in the array), and must return a number which indicates whether they are equal (0), whether the first object should be first in order (-1) or whether the first object should be last in order (1).

This comparison function sorts the array in reverse:

var x = [2, 1, 3];
x.sort(function (a, b) { // here we are passing this custom comparison function into the sort function, as a parameter
    if (a == b) return 0;  // if the two numbers being compared are equal, don't change the order
    if (a < b)  return 1;  // if the first number is smaller, place it after (+1)
    else        return -1; // otherwise the first number is bigger, so place it before (-1)
});
alert(x.toString()); // shows 3, 2, 1

Because the sort function really checks to see whether the comparison returned a negative or positive number (or 0), the above comparison function could have been written more succinctly as:

x.sort(function (a, b) {
    // if the numbers are equal, b - a = 0
    // if b is smaller than a, a negative number is returned (placing b after a in the sorted array)
    return b - a;
});

Sorting one array by the values of another array

If you have two arrays of values with the same number of items, you can sort one array by the order of values in the other array. The trick is to make a third array which keeps track of which items in the array represent each other.

For example, you may have an array of labels, and an array of values for each label.

var fruit = ['Apple', 'Lychee', 'Mandarin']; // names of fruit
var price = [5.00,    10.00,    2.00];       // prices of fruit

Recognising that you can make a number to represent each fruit and its price (0 is Apple at $5.00, 1 is Lychee at $10.00, 2 is Mandarin at $2.00), you can make an array of the numbers and sort by that instead:

var fruit = ['Apple', 'Lychee', 'Mandarin']; // names of fruit
var price = [5.00,    10.00,    2.00];       // prices of fruit
var numbers = [0, 1, 2];
numbers.sort(function (a, b) { // 'a' and 'b' are numbers which we use to access the prices of fruit
    var price_a = price[a]; // get the price for fruit 'a'
    var price_b = price[b]; // get the price for fruit 'b'
    return price_a - price_b; // sort by the price in increasing order
});
alert(numbers.toString()); // shows 2, 0, 1

var cheapest_fruits = []; // make a new array
for (var i = 0; i < numbers.length; i++) {
    var fruit_number = numbers[i]; // get the number for the fruit (cheapest first)
    cheapest_fruits[i] = fruit[fruit_number]; // add the name of the fruit
}
alert(cheapest_fruits.toString()); // shows Mandarin, Apple, Lychee

For a more practical (yet more complicated) example, see Sorting Tables By the Largest Column.

Sorting a copy of an array

Be careful, because the sort function modifies the original array.

var x = [2, 1, 3];
var y = x.sort(); // this modifies 'x' and also returns 'x', but we are giving it a new name as if it is different (a common mistake)
alert(x.toString()); // shows 3, 2, 1
alert(y.toString()); // shows 3, 2, 1

If you don't want to change the original array, you should make a copy using the splice function.

var x = [2, 1, 3];
var y = x.splice(0); // this creates a new array with the same objects inside
y.sort();
alert(x.toString()); // shows 2, 1, 3
alert(y.toString()); // shows 3, 2, 1

See also

Arrays