JavaScript Sort an Array of Objects
I ran into an interesting problem today. I had an array of objects that I wanted sorted on a certain property. My obvious thought didn’t work! (Update: I got a comment below from Peter Michaux who points out a nicer solution, it is included here:)
// Array of Objects
var obj_arr = age: 21name: "Larry"
age: 34name: "Curly"
age: 10name: "Moe" ;
// This doesn't work!
obj_arrsort functionab return aname < bname; ;
// This does work! (Peter's update, very fast)
obj_arr1sortfunctionab return aname < bname ? -1 :
aname > bname ? 1 : 0; ;
That kind of frustrated me. Sorting is one of those things I expect to be available in all languages. I don’t want to have to write a sorting algorithm every time I need to sort. So I looked into things, pulled up a Javascript Quicksort Algorithm and manipulated it to support any compare function.
Now that I have the freedom to truly write a compare function that works for objects! I also changed around certain parts of the code I found online to actually extend the Array class and make the extra functions hidden. Take a look at the sample usage:
// Defaults to (a<=b) sorting. Great for numbers.
var arr = 123423462123434563213434561234234523425231234345;
// Object Array
var obj_arr = age: 21name: "Larry"
age: 34name: "Curly"
age: 10name: "Moe" ;
arrquick_sort;
// => [23, 345, 1234, 1234, 1234, 2345, 2346, 3456, 3456, 21234, 32134, 42523]
obj_arrquick_sortfunctionab return aname < bname ;
// => Curly, Larry, Moe
obj_arrquick_sortfunctionab return aage < bage ;
// => Moe (10), Larry (21), Curly (34)
For those who want to see the code be glad, its free. I carried the copyright with it but its rather loose. Grab the JavaScript Source Here! Enjoy:
var tmp=thisa;
thisa=thisb;
thisb=tmp;
var piv = arraypivot;
arrayswappivotend-1;
var store = begin;
for var ix = begin; ix < end-1; ++ix
if compareFunctionarrayixpiv
arrayswapstoreix;
++store;
arrayswapend-1store;
return store;
if end-1 > begin
var pivot = begin + MathfloorMathrandom * end-begin;
pivot = partitionarraycompareFunctionbeginendpivot;
qsortarraycompareFunctionbeginpivot;
qsortarraycompareFunctionpivot+1end;
if compareFunction == null
return a<=b; ;
qsortthiscompareFunction0thislength;
Update
Peter Michaux pointed out something very important. The sort() function can be made to work if it returns numeric output (-1,0,1). His approach is far superior. Here was a benchmark I took:
var obj_arr1 = ;
var obj_arr2 = ;
var filler = age: 21name: "Larry"
age: 34name: "Curly"
age: 10name: "Moe" ;
for var i=0; i<5000; i++
rand = Mathfloor Mathrandom * 3 ;
obj_arr1push fillerrand ;
obj_arr2push fillerrand ;
var s = ;
obj_arr1sortfunctionab return aname < bname ? -1 : aname > bname ? 1 : 0; ;
var e = ;
console.logegetTime-sgetTime; // => 75 ms
s = ;
obj_arr2quick_sortfunctionab return aname < bname ;
e = ;
console.logegetTime-sgetTime; // => 4444 ms
That shows drastic differences for arrays as large as 5000 elements (with not too random data). 75 ms versus 4444 ms (over 4 seconds). Doing the math: (4444/75) => 59.253 times better! Moral of the story, don’t rush into thinking something doesn’t exist!
So if that’s the way to do it, then I want to make it easier on me. My arrays are generally going to be under 100 in size, and at such a size building a function dynamically instead of writing a custom function works just about as well (although if you were using objects, polymorphism and a compare function would be the best way to go). Here is a simple function I can use to more quickly build compare functions in order to ascend sort an array on multiple properties!
if arr && arrlength > 0
return functionab
var asubbsubprop;
for var i=0; i<arrlength; i++
prop = arri;
asub = aprop;
bsub = bprop;
if asub < bsub
return -1;
if asub > bsub
return 1;
return 0;
else
return functionab return a<=b; ;
Sample usage would be:
var obj_arr =
name: 'Joe'age: 20
name: 'Joe'age: 10
name: 'Joe'age: 30
name: 'Joe'age: 40
name: 'Joe'age: 20
name: 'Joe'age: 15
name: 'Joe'age: 35
name: 'Joe'age: 25
name: 'Bill'age: 5
name: 'Barry'age: 20
name: 'Paul'age: 20
name: 'Peter'age: 1
name: 'Smith'age: 25
name: 'Kary'age: 30
;
obj_arrsort buildCompareFunction'name''age';

15. June 2008 um 02:07
JavaScript’s sort works a little differently than you expected
var obj_arr = [ { age: 21, name: "Larry" },
{ age: 34, name: "Curly" },
{ age: 10, name: "Moe" } ];
obj_arr.sort( function(a,b) {
return a.name < b.name ? -1 :
a.name > b.name ? 1 : 0; });
15. June 2008 um 02:16
@Peter: You’re right. I expected it to sort based on true or false but I just re-read w3school’s definition which I scanned over and it says: “you must create a function that compares numbers”.
You bring up a good point and I bet that a benchmark of yours will blow mine out of the water. Its just a tad too late for me to check it out now. I’ll take a look later and update the post. Thanks for point that out!