Say I have an array of JavaScript objects:

var objs = [ { first_nom: 'Lazslo',last_nom: 'Jamf' },
            { first_nom: 'Pig', last_nom: 'Bodine'  },
            { first_nom: 'Pirate', last_nom: 'Prentice' }
           ];

How can I sort them by the value of last_nom in JavaScript?

I know about sort(a,b), but that only seems to work on strings and numbers. Do I need to add a toString method to my objects?

share|improve this question
1  
Bonus points for names taken from Gravity's Rainbow. – Kris Giesing Jul 4 '12 at 19:07

8 Answers

up vote 148 down vote accepted

It's easy enough to write your own comparison function:

function compare(a,b) {
  if (a.last_nom < b.last_nom)
     return -1;
  if (a.last_nom > b.last_nom)
    return 1;
  return 0;
}

objs.sort(compare);
share|improve this answer
1  
thanks. Didn't know that sort took a function ref. – Tyrone Slothrop Jul 15 '09 at 3:45
23  
Or inline: objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} ); – Marco Demaio Feb 24 '10 at 18:29
1  
Nice example, worked perfectly – iancrowther Dec 5 '11 at 13:52
Thank you very much, but i'm struggling to see the logic that function follows... what is a & b? are they the 1st and 2nd, then 2nd,3rd then 3rd,4th?!? – Will Hancock Apr 19 '12 at 11:12
3  
show 1 more comment

You can also create a dynamic sort function that sorts objects by their value that you pass:

function dynamicSort(property) {
    var sortOrder = 1;
    if(property[0] === "-") {
        sortOrder = -1;
        property = property.substr(1, property.length - 1);
    }
    return function (a,b) {
        var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
        return result * sortOrder;
    }
}

So you can have an array of objects like this:

var People = [
    {Name: "Name", Surname: "Surname"},
    {Name:"AAA", Surname:"ZZZ"},
    {Name: "Name", Surname: "AAA"}
];

...and it will work when you do:

People.sort(dynamicSort("Name"));
People.sort(dynamicSort("Surname"));
People.sort(dynamicSort("-Surname"));

I wouldn't recommend changing a native object prototype but just to give an example so you can implement it on your own objects (For the environments that support it, you can also use Object.defineProperty, which doesn't have the negative side-effects of fiddling with a native object's prototype):

Array.prototype.sortBy = function(property) {
    return this.sort(dynamicSort(property))
}

then you can do stuff like:

People.sortBy("Name");

Hope it helps.

Update: You can use the function below to generate sort functions with multiple sort parameters.

function dynamicSortMultiple() {
    /*
     * save the arguments object as it will be overwritten
     * note that arguments object is an array-like object
     * consisting of the names of the properties to sort by
     */
    var props = arguments;
    return function (obj1, obj2) {
        var i = 0, result = 0, numberOfProperties = props.length;
        /* try getting a different result from 0 (equal)
         * as long as we have extra properties to compare
         */
        while(result === 0 && i < numberOfProperties) {
            result = dynamicSort(props[i])(obj1, obj2);
            i++;
        }
        return result;
    }
}

Which would enable you to do something like this:

People.sort(dynamicSortMultiple("Name", "-Surname"));

This can also be extended to have custom functions for comparison easily.

share|improve this answer
1  
Love the dynamicSortMultiple! – Heather Dec 17 '12 at 23:43
Please note that property names in JavaScript can be any string and if you have properties starting with a "-" (extremely unlikely and probably not a good idea), you'll need to modify the dynamicSort function to use something else as a reverse sort indicator. – Ege Özcan Jan 10 at 15:18

If you have duplicate last names you might sort those by first name-

obj.sort(function(a,b){
  if(a.last_nom< b.last_nom) return -1;
  if(a.last_nom >b.last_nom) return 1;
  if(a.first_nom< b.first_nom) return -1;
  if(a.first_nom >b.first_nom) return 1;
  return 0;
}
share|improve this answer
Thanks, this was what I was looking for! – Sean Jul 9 '12 at 18:55

Instead of using a custom comparison function, you could also create an object type with custom toString() method (which is invoked by the default comparison function):

function Person(firstName, lastName) {
    this.firtName = firstName;
    this.lastName = lastName;
}

Person.prototype.toString = function() {
    return this.lastName + ', ' + this.firstName;
}

var persons = [ new Person('Lazslo', 'Jamf'), ...]
persons.sort();
share|improve this answer

This script allows you to do just that unless you want to write your own comparison function or sorter:

http://www.thomasfrank.se/sorting_things.html

share|improve this answer

underscore.js

use underscore, its small and awesome...

sortBy_.sortBy(list, iterator, [context]) Returns a sorted copy of list, ranked in ascending order by the results of running each value through iterator. Iterator may also be the string name of the property to sort by (eg. length).

var objs = [ { first_nom: 'Lazslo',last_nom: 'Jamf' },
        { first_nom: 'Pig', last_nom: 'Bodine'  },
        { first_nom: 'Pirate', last_nom: 'Prentice' }
       ];

_.sortBy( objs, 'first_nom' );
share|improve this answer

additional desc params for Ege Özcan code

function dynamicSort(property, desc) {
    if (desc) {
        return function (a, b) {
            return (a[property] > b[property]) ? -1 : (a[property] < b[property]) ? 1 : 0;
        }   
    }
    return function (a, b) {
        return (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;
    }
}
share|improve this answer
+1 for added dynamics, still simple – hubson bropa Oct 31 '12 at 21:20

Simple and quick solution to this problem using prototype inheritance.

Solution

Array.prototype.sortByProp = function(p){
 return this.sort(function(a,b){
  return (a[p] > b[p]) ? 1 : (a[p] < b[p]) ? -1 : 0;
 });
}

Example / Usage

objs = [{age:44,name:'vinay'},{age:24,name:'deepak'},{age:74,name:'suresh'}];

objs.sortByProp('age');
// Returns
// [{"age":24,"name":"deepak"},{"age":44,"name":"vinay"},{"age":74,"name":"suresh"}]

objs.sortByProp('name');
// Returns
// [{"age":24,"name":"deepak"},{"age":74,"name":"suresh"},{"age":44,"name":"vinay"}]
share|improve this answer
It dosn't just return another array. but actually sorts the original one!. – Vinay Aggarwal Jul 21 '12 at 5:43

Your Answer

 
or
required, but never shown
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.