JavaScript Object Array Sorting: Using Custom Comparison Function


Array is a very necessary data structure for programming. In JavaScript also, we have Array Object. It is quite natural that we will need to sort the elements of the array, sometimes in ascending order or descending order. While it is an array of string, it is easy to do the sorting. We have a sort method in the array object and that can do our job. But when we have an object array and we need to sort the objects based on some custom defined nature, we need to think a bit more. We will see some examples of array sorting in this post.


Declaring a JavaScript Array:

We can declare a blank array as follows:

var js_array = [];

There is another alternative for declaring a blank array.

var js_array = new Array();

If we need to have an array with some initial values, then we can do it as follows:

var js_array = [1, 20, 3, 12, 21, 5];
var js_array = ['item 3''item 1''item 2''item 5''item 4'];


Creating an Array of objects:

Suppose we have a Pair Class defined as below. The Pair class takes to parameters. One is x and the other is y. The Pair class contains a method tostring(). Infact, every object has a tostring()method. But for our class, we want it to show a string of our own. This toString() method returns a string in the form of (x, y).

function Pair(a, b) {
this.x = a;
this.y = b;
this.toString = function() {
return '(' + this.x + ', ' + this.y + ')';
}
}

So if we want to create an array of Pairs, we can do it easily. We can create a Pair object as

var aPair = new Pair(rand_x, rand_y);
var js_obj_array = [];
for (var i = 0; i < 10; i++) {
var rand_x = Math.round(Math.random()*100);
var rand_y = Math.round(Math.random() * 100);
js_obj_array.push(new Pair(rand_x, rand_y));
}


Sorting a JavaScript Array:

Now we will see how to sort an array. Really simple.

var js_array = ['item 3''item 1''item 2''item 5''item 4'];
alert(js_array.join(','));
//the result will show
//item 3,item 1,item 2,item 5,item 4
js_array.sort();
alert(js_array.join(','));
//the result will show
//item 1,item 2,item 3,item 4,item 5

This is good. But if we try to sort an array with some numbers, we have some problem.

var js_array = [1, 20, 3, 12, 21, 5];
alert(js_array.join(','));
//the result will show
//1,20,3,12,21,5
js_array.sort();
alert(js_array.join(','));
//the result will show
//1,12,20,21,3,5

We see here that the array is not sorted properly. It is infact sorting the numbers in lexicographical order. This is surely not what we expect. So need some work around to do a correct sorting.
The sort method in Array accepts a function, a comparison function. We can define this ourselves to decide which element is smaller and which element is larger. The comparison function must return negative number to indicate that the former element is smaller than the later element. It must return positive number to indication that the former element is larger than the later element. It must return 0 to indicate that both the elements are equal.

var int_comparison = function(a, b) {
return a - b;
}
var js_array = [1, 20, 3, 12, 21, 5];
alert(js_array.join(','));
//the result will show
//1,20,3,12,21,5
js_array.sort(int_comparison);
alert(js_array.join(','));
//the result will show
//1,3,5,12,20,21

We can also do it using anonymous function. No need to have a separate function defined.

var js_array = [1, 20, 3, 12, 21, 5];
alert(js_array.join(','));
//the result will show
//1,20,3,12,21,5
js_array.sort(function(a, b) {
return a - b;
});
alert(js_array.join(','));
//the result will show
//1,3,5,12,20,21

So infact what we are doing is just telling the sort method not to decide the position of the elements using default comparison, but to use our method to decide which element is smaller and which is larger.


Sorting Array in descending Order:

Now if we want to sort the array elements in descending order, it is quite simple.

var js_array = [1, 20, 3, 12, 21, 5];
alert(js_array.join(','));
//the result will show
//1,20,3,12,21,5
js_array.sort(function(a, b) {
return b - a;
});
alert(js_array.join(','));
//the result will show
//21,20,12,5,3,1


Sorting Array of Objects:

We have already created an array of Pair objects. There is no default sorting for this. Because, there is no way for the sort method to know which element is smaller and which is larger.

var js_array = [];
for (var i = 0; i < 10; i++) {
var rand_x = Math.round(Math.random()*100);
var rand_y = Math.round(Math.random() * 100);
js_array.push(new Pair(rand_x, rand_y));
}
var comparison_function = function(a, b) {
if (a.x < b.x)
return -1;
else if (a.x > b.x)
return 1;
else if (a.y < b.y)
return -1;
else if (a.y > b.y)
return 1;
else
return 0;
}
alert(js_array.join(','));
//the result will show
//(68, 23),(12, 53),(49, 55),(38, 48),(70, 62),(9, 97),(67, 91),(12, 63),(46, 77),(41, 33)
alert(js_array.sort().join(','));
//the result will show
//(18, 87),(2, 16),(24, 55),(26, 40),(58, 55),(63, 13),(66, 16),(72, 44),(72, 55),(85, 69)
alert(js_array.sort(comparison_function).join(','));
//the result will show
//(2, 16),(18, 87),(24, 55),(26, 40),(58, 55),(63, 13),(66, 16),(72, 44),(72, 55),(85, 69)

First we see the random Pair generated. Without the comparison method, we see that the array is sorted again using the string comparison. Class Pair has a toString defined. The sort method took the string for every element and then it used a simple string comparison and sorted the array. But we want a different sorting. So we defined the comparison_function. It is very important to notice how we used the objects in the comparison function. The sort method will send the elements of the array to our comparison function. As the elements are objects, so we will receive object of type Pair. Now we can easily access the properties of the objects and can write any algorithm we want to use for our sorting. But we have to be careful that our comparison function must return negative, positive and 0 as we mentioned earlier.
So this way we can infact sort any object array, any way we want.

No comments:

Post a Comment