By Tyrone Slothrop


2009-07-15 03:17:47 8 Comments

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?

30 comments

@SwiftNinjaPro 2019-11-25 02:03:38

Hers a function you can use to sort the list by multiple objects, where if the first object is equal, the second order will be used as a fallback. empty values should also be ignored to fallback order if possible.

function sortObjects(list, orderBy){
    list.sort(function(a, b){
        let byIndex = 0;
        let order = orderBy[byIndex];
        while(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            byIndex++;
            if(byIndex >= orderBy.length){break;}
            order = orderBy[byIndex];
        }
        if(!a[order.by] || !b[order.by] || a[order.by] === b[order.by]){
            return false;
        }
        if(order.desc){
            return a[order.by] < b[order.by];
        }
        return a[order.by] > b[order.by];
    });
    return list;
}

usage:

var objs = [
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
];

sortObjectList(objs, [{by: 'a'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 20, b: 10, c: 30},
    {a: 30, b: 10, c: 20},
]

sortObjectList(objs, [{by: 'a', desc: true}]);
[
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
    {a: 10, b: 20, c: 30},
]

sortObjectList(objs, [{by: 'b', desc: true}, {by: 'c'}]);
[
    {a: 10, b: 20, c: 30},
    {a: 30, b: 10, c: 20},
    {a: 20, b: 10, c: 30},
]

another example:

var objs = [
    {a: 5, b: 5},
    {a: 10, b: 15},
    {a: 15, b: 25},
    {b: 10},
    {b: 20},
    {a: 10, b: 30},
    {a: 10, b: 12},
];

sortObjectList(objs, [{by: 'a'}, {by: 'b'}]);
[
    {a: 5, b: 5},
    {b: 10},
    {a: 10, b: 12},
    {a: 10, b: 15},
    {b: 20},
    {a: 10, b: 30},
    {a: 15, b: 25},
]

@Amit Jadli 2019-11-19 11:15:33

this sorting funciton can be use for all object sorting,

  • object

  • deepObject

  • numeric array

you can also do assending or desending sort by passing 1,-1 as param

Object.defineProperty(Object.prototype, 'deepVal', {
    enumerable: false,
    writable: true,
    value: function (propertyChain) {
        var levels = propertyChain.split('.');
        parent = this;
        for (var i = 0; i < levels.length; i++) {
            if (!parent[levels[i]])
                return undefined;
            parent = parent[levels[i]];
        }
        return parent;
    }
});


function dynamicSortAll(property,sortOrders=1) {

/**default sorting will be ascending order if you need descending order
sording you have to pass -1 as param**/

    var sortOrder = sortOrders;
   
    return function (a,b) {

		 var result =(property? ((a.deepVal(property) > b.deepVal(property)) ? 1 : (a.deepVal(property) < b.deepVal(property)) ? -1 : 0) :((a > b) ? 1 : (a < b) ? -1 : 0))
		
        return result * sortOrder;
		
   
    }
}

deepObj = [
    {
        a: { a: 1, b: 2, c: 3 },
        b: { a: 4, b: 5, c: 6 }
    },
    { 
        a: { a: 3, b: 2, c: 1 },
        b: { a: 6, b: 5, c: 4 }
}];

let deepobjResult=deepObj.sort(dynamicSortAll('a.a',1))
console.log('deepobjResult :'+ JSON.stringify(deepobjResult))
var obj = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
let objResult=obj.sort(dynamicSortAll('last_nom',1))
console.log('objResult :'+ JSON.stringify(objResult))

var numericObj=[1,2,3,4,5,6]

let numResult=numericObj.sort(dynamicSortAll(null,-1))
console.log('numResult :'+ JSON.stringify(numResult))

let stringSortResult='helloworld'.split('').sort(dynamicSortAll(null,1))

 console.log('stringSortResult:'+ JSON.stringify(stringSortResult))

let uniqueStringOrger=[...new Set(stringSortResult)]; 
 console.log('uniqueStringOrger:'+ JSON.stringify(uniqueStringOrger))

@Vlad Bezden 2016-01-29 19:44:37

In ES6/ES2015 or later you can do this way:

objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom));

Prior to ES6/ES2015

objs.sort(function(a, b) {
    return a.last_nom.localeCompare(b.last_nom)
});

@Jon Harding 2016-02-22 20:30:59

this has been available since JS 1.1, the fat arrow piece to this is the ES6/2015 piece. But still very useful, and best answer in my opinion

@Vlad Bezden 2016-05-26 18:24:21

@PratikKelwalkar: if you need reverse it just switch a and b comparison: objs.sort((a, b) => b.last_nom.localeCompare(a.last_nom));

@and-bri 2017-05-29 18:15:52

is it possible to use a index as well to address the field for sorting: instead of last_nom use just the number in the array: 1 ?

@scipper 2018-01-09 08:49:39

@VladBezden thanks for your answer! This solution is the first with very small programmatic effort and correct sorting results and a string array like: ["Name1", "Name10", "Name2", "something else", "Name11"]. I got sorting to work correctly with objs.sort((a, b) => a.last_nom.localeCompare(b.last_nom, undefined, {numberic: true}));

@Sebastian Patten 2019-05-23 05:05:58

To do this with numbers descending: .sort((a, b) => b.numberProperty - a.numberProperty). Ascending: .sort((a, b) => a.numberProperty - b.numberProperty)

@Ege Özcan 2011-01-21 15:03:06

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);
    }
    return function (a,b) {
        /* next line works with strings and numbers, 
         * and you may want to customize it to your needs
         */
        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"));

Actually this already answers the question. Below part is written because many people contacted me, complaining that it doesn't work with multiple parameters.

Multiple Parameters

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"));

Subclassing Array

For the lucky among us who can use ES6, which allows extending the native objects:

class MyArray extends Array {
    sortBy(...args) {
        return this.sort(dynamicSortMultiple.apply(null, args));
    }
}

That would enable this:

MyArray.from(People).sortBy("Name", "-Surname");

@Ege Özcan 2013-01-10 15:18:39

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.

@Lloyd Banks 2017-07-26 22:06:50

I've noticed that the dynamicSort() in the above example will place capital letters ahead of lowercase letters. For example, if I have the values APd, Aklin, and Abe - the results in an ASC sort should be Abe, Aklin, APd. But with your example, the results are APd, Abe, Aklin. Anyway to correct this behavior?

@Ege Özcan 2017-08-06 08:55:17

@LloydBanks if you are using this strictly for strings, then you can use var result = a[property].localeCompare(b[property]); instead of var result = (a[property] < b[property]) ? -1 : (a[property] > b[property]) ? 1 : 0;.

@dzh 2018-01-19 04:09:11

Just like a top answer, this one fails in cases where undefine properties exist: [ { a: 5 }, {a:2}, {}, {a:1} ]

@Ege Özcan 2018-01-19 16:57:28

@Dzh um, how should the undefined key be handled? There are different things you can do to make that work. 1) Get a default value and use it in comparison like a[property] || defaultVal. 2) Always return -1 (or 1 maybe) if a[property] is null. This is a Turing-complete language, you can't possibly handle all the cases. What happens when a is a getter which throws? There could be unlimited number of cases.

@dzh 2018-01-20 00:37:17

@EgeÖzcan It should either put items to the top or bottom, here's implementation I've ended up using pastebin.com/g4dt23jU

@Ege Özcan 2018-01-23 15:22:07

@Dzh you can add the same escape ( || '' ) above as well and it would work the same. There is no one-size-fits-all solution when it comes to sorting objects.

@Ivijan Stefan Stipić 2018-04-03 05:48:02

This is great solution but have one problem if you compare numbers. Please add this before check: if( !isNaN(a[property]) ) a[property] = Number(a[property]); if( !isNaN(b[property]) ) b[property] = Number(b[property]);

@Zilvinas 2019-02-07 19:10:06

This is great! And all the hasOwnProperty issues could be avoided if one would just use a util class. Util.sortBy( People, "Name", "-Surname" ) & etc.

@Ege Özcan 2019-05-18 15:14:36

@Zilvinas I added a subclass example, but exposing a utility function could indeed be better depending on the codebase.

@Ferrybig 2019-05-07 13:38:32

It is also possible to make a dynamic sorting function when programming in TypeScript, but the types become more tricky in this case.

function sortByKey<O>(key: keyof O, decending: boolean = false): (a: O, b: O) => number {
    const order = decending ? -1 : 1;
    return (a, b): number => {
        const valA = a[key];
        const valB = b[key];
        if (valA < valB) {
            return -order;
        } else if (valA > valB) {
            return order;
        } else {
            return 0;
        }
    }
}

This can be used in TypeScript as the following:

const test = [
    {
        id: 0,
    },
    {
        id: 2,
    }
]

test.sort(sortByKey('id')) // OK
test.sort(sortByKey('id1')) // ERROR
test.sort(sortByKey('')) // ERROR

@Patrick Roberts 2018-07-18 09:53:13

I haven't seen this particular approach suggested, so here's a terse comparison method I like to use that works for both string and number:

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

const sortBy = fn => (a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}
const getLastName = o => o.last_nom
const sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))

Here's an explanation of sortBy():

sortBy() accepts a fn that selects what value from an object to use as comparison, and returns a function that can be passed directly to Array.prototype.sort(). In this example, we're using o.last_nom as the value for comparison, so whenever we receive two objects through Array.prototype.sort() such as

{ first_nom: 'Lazslo', last_nom: 'Jamf' }

and

{ first_nom: 'Pig', last_nom: 'Bodine' }

we use

(a, b) => {
  const fa = fn(a)
  const fb = fn(b)
  return -(fa < fb) || +(fa > fb)
}

to compare them.

Remembering that fn = o => o.last_nom, we can expand the compare function to the equivalent

(a, b) => {
  const fa = a.last_nom
  const fb = b.last_nom
  return -(fa < fb) || +(fa > fb)
}

The logical OR || operator has a short-circuiting functionality that's very useful here. Because of how it works, the body of the function above means

if (fa < fb) return -1
return +(fa > fb)

So if fa < fb we return -1, otherwise if fa > fb then we return +1, but if fa == fb, then fa < fb and fa > fb are false, so it returns +0.

As an added bonus, here's the equivalent in ECMAScript 5 without arrow functions, which is unfortunately more verbose:

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

var sortBy = function (fn) {
  return function (a, b) {
    var fa = fn(a)
    var fb = fn(b)
    return -(fa < fb) || +(fa > fb)
  }
}

var getLastName = function (o) { return o.last_nom }
var sortByLastName = sortBy(getLastName)

objs.sort(sortByLastName)
console.log(objs.map(getLastName))

@Wogan 2009-07-15 03:35:51

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 );

Or inline (c/o Marco Demaio):

objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)); 

@Marco Demaio 2010-02-24 18:29:10

Or inline: objs.sort(function(a,b) {return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0);} );

@Will Hancock 2012-04-19 11:12:27

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?!?

@mikemaccana 2012-05-18 09:11:15

@Cerbrus 2013-02-14 10:37:20

return a.last_nom.localeCompare(b.last_nom) will work, too.

@nelsonic 2013-05-09 18:12:19

If wants the CoffeeScript one-liner for this: objs.sort (a,b) -> return (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0)

@Andre Figueiredo 2014-01-08 12:06:25

for those looking for a sort where the field is numeric, the compare function body: return a.value - b.value; (ASC)

@mattdlockyer 2014-02-13 20:27:32

Many hints to this can be found on the MDN pages: developer.mozilla.org/en/docs/Web/JavaScript/Reference/…

@Sophiα2329 2015-01-02 22:19:39

@MarcoDemaio var m=a.last_nom,n=b.last_nom; return m>n-m<n True forced to number is 1, false 0.

@jherax 2015-03-30 23:32:13

@Jim Buck 2015-05-19 15:48:31

The biggest issue with this answer is the lack of details when it comes to dealing with possibly null or undefined properties. I've updated it to include an explanation and detailed implementation.

@0xcaff 2015-12-26 22:30:11

What happens if your sort computation is expensive, how does sort prevent re-comparing the same values?

@Joshua Pinter 2016-02-24 23:51:10

I know it's verbose creating a whole compare function but man does it make following the logic easier. Thanks.

@Fergal 2016-05-19 07:51:55

Because we all love the ternary operator: objs.sort(function compare(a,b) { return a.val < b.val ? -1 : a.val > b.val ? 1 : 0; });

@Marcos Lima 2016-06-01 16:38:05

@Cerbrus localeCompare is important when using accented characters in foreign languages, and more elegant as well.

@Eugene Balashov 2016-10-06 08:40:37

whats wrong in: TypeError: obj.sort is not a function. (In 'compare.sort(compare)', 'obj.sort' is undefined)

@Luckylooke 2017-03-20 10:37:33

@Cerbrus localeCompare in browsers support is IE11+ :/

@mwardm 2017-04-27 11:04:40

@Luckylooke You need IE11 for the optional [, locales][, options] parameters; the localeCompare function itself is supported in earlier versions of IE.

@Fl4v 2017-09-13 15:34:45

Or, with ES6 style : objs.sort((a,b) => (a.last_nom > b.last_nom) ? 1 : ((b.last_nom > a.last_nom) ? -1 : 0));

@dzh 2018-01-19 04:06:43

Answer completely fails with basic example like [ { a: 5 }, {a:2}, {}, {a:1} ]

@Kaushik 2018-02-13 06:52:27

if the key value is mixed with lower case and the upper case then we can make that toLowerCase() and then it will work. otherwise sorting won't work. it will sort all which is starting with uppercase and then the values with lower case.

@Farhad 2018-05-09 19:11:41

re @MarcoDemaio in typescript :: objs.sort( (a: any, b: any) => { return (a.order && b.order) ? (( a.order > b.order ) ? 1 : ( ( b.order > a.order ) ? -1 : 0 )) : 0; } );

@sg28 2018-07-12 23:34:56

Array.sort() is unstable (Moz says itself) ,doesn't work all the time

@Walaszka 2018-09-19 13:58:52

And if you look for comparing multiple properties with accented characters you can use return a.lastname.localeCompare(b.lastname) || a.firstname.localeCompare(b.firstname);

@Ninja Coding 2018-09-25 20:38:23

localeCompare is important when order is case insensitive: A a b C c... (the answer example is case sensitive: A C a b c...)

@Jimeh 2019-04-29 17:33:15

A gotcha with using the accepted answer is if last_nom is null or undefined, the comparison will always return 0 instead of -1 or 1.

@Akitha_MJ 2019-07-24 08:29:57

if someone has a issue of understanding the logic follow this Arr.sort((a,b) => a-b); explanation

@shaheer shukur 2019-09-05 06:40:31

consider adding toLowerCase() to variables during comparison, else uppercase alphabets will come before lowercase alphabets.

@Jamie Mason 2014-04-30 10:02:43

Example Usage:

objs.sort(sortBy('last_nom'));

Script:

/**
 * @description
 * Returns a function which will sort an
 * array of objects by the given key.
 *
 * @param  {String}  key
 * @param  {Boolean} reverse
 * @return {Function}
 */
const sortBy = (key, reverse) => {

  // Move smaller items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveSmaller = reverse ? 1 : -1;

  // Move larger items towards the front
  // or back of the array depending on if
  // we want to sort the array in reverse
  // order or not.
  const moveLarger = reverse ? -1 : 1;

  /**
   * @param  {*} a
   * @param  {*} b
   * @return {Number}
   */
  return (a, b) => {
    if (a[key] < b[key]) {
      return moveSmaller;
    }
    if (a[key] > b[key]) {
      return moveLarger;
    }
    return 0;
  };
};

@Chris22 2018-08-22 06:23:56

thank you for breaking this down, I am trying to understand why digits 1, 0, -1 are used for sort ordering. Even with your explanation above, which looks very good-- I'm still not quite understanding it. I always think of -1 as when using array length property, i.e.: arr.length = -1 means that the item isn't found. I'm probably mixing things up here, but could you help me understand why digits 1, 0, -1 are used to determine order? Thanks.

@Jamie Mason 2018-08-23 09:09:35

This isn't entirely accurate but it might help to think of it like this: the function passed to array.sort is called once for each item in the array, as the argument named "a". The return value of each function call is how the index (current position number) of item "a" should be altered compared to the next item "b". The index dictates the order of the array (0, 1, 2 etc) So if "a" is at index 5 and you return -1 then 5 + -1 == 4 (move it nearer front) 5 + 0 == 5 (keep it where it is) etc. It walks the array comparing 2 neighbours each time until it reaches the end, leaving a sorted array.

@Chris22 2018-08-23 16:28:58

thank you for taking the time to explain this further. So using your explanation and the MDN Array.prototype.sort, I'll tell you what I'm thinking of this: in comparison to a and b, if a is greater than b add 1 to the index of a and place it behind b, if a is less than b, subtract 1 from a and place it in front of b. If a and b are the same, add 0 to a and leave it where it is.

@Mas 2019-03-16 18:12:15

In case you have nested objects

const objs = [{
        first_nom: 'Lazslo',
        last_nom: 'Jamf',
        moreDetails: {
            age: 20
        }
    }, {
        first_nom: 'Pig',
        last_nom: 'Bodine',
        moreDetails: {
            age: 21
        }
    }, {
        first_nom: 'Pirate',
        last_nom: 'Prentice',
        moreDetails: {
            age: 22
        }
    }];

nestedSort = (prop1, prop2 = null, direction = 'asc') => (e1, e2) => {
        const a = prop2 ? e1[prop1][prop2] : e1[prop1],
            b = prop2 ? e2[prop1][prop2] : e2[prop1],
            sortOrder = direction === "asc" ? 1 : -1
        return (a < b) ? -sortOrder : (a > b) ? sortOrder : 0;
    }

and call it like

objs.sort(nestedSort("last_nom"));
objs.sort(nestedSort("last_nom", null, "desc"));
objs.sort(nestedSort("moreDetails", "age"));
objs.sort(nestedSort("moreDetails", "age", "desc"));

@Harshal 2018-08-23 14:39:00

You can use

Easiest Way: Lodash

(https://lodash.com/docs/4.17.10#orderBy)

This method is like _.sortBy except that it allows specifying the sort orders of the iteratees to sort by. If orders is unspecified, all values are sorted in ascending order. Otherwise, specify an order of "desc" for descending or "asc" for ascending sort order of corresponding values.

Arguments

collection (Array|Object): The collection to iterate over. [iteratees=[_.identity]] (Array[]|Function[]|Object[]|string[]): The iteratees to sort by. [orders] (string[]): The sort orders of iteratees.

Returns

(Array): Returns the new sorted array.


var _ = require('lodash');
var homes = [
    {"h_id":"3",
     "city":"Dallas",
     "state":"TX",
     "zip":"75201",
     "price":"162500"},
    {"h_id":"4",
     "city":"Bevery Hills",
     "state":"CA",
     "zip":"90210",
     "price":"319250"},
    {"h_id":"6",
     "city":"Dallas",
     "state":"TX",
     "zip":"75000",
     "price":"556699"},
    {"h_id":"5",
     "city":"New York",
     "state":"NY",
     "zip":"00010",
     "price":"962500"}
    ];

_.orderBy(homes, ['city', 'state', 'zip'], ['asc', 'desc', 'asc']);

@chandan gupta 2018-07-05 11:14:21

It works for me. Here It will keep undefined to the end.

 function sort(items, property, direction) {

    function compare(a, b) {
      if(!a[property] && !b[property]) {
        return 0;
      } else if(a[property] && !b[property]) {
        return -1;
      } else if(!a[property] && b[property]) {
        return 1;
      } else {
        const value1 = a[property].toString().toUpperCase(); // ignore upper and lowercase
        const value2 = b[property].toString().toUpperCase(); // ignore upper and lowercase
        if (value1 < value2) {
          return direction === 0 ? -1 : 1;
        } else if (value1 > value2) {
          return direction === 0 ? 1 : -1;
        } else {
          return 0;
        }
        
      }
    }
    
    return items.sort(compare);
   } 
   
   var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: undefined, value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];
   console.log('Ascending Order:- ');
   console.log(sort(items, 'name', 0));
   console.log('Decending Order:- ');
   console.log(sort(items, 'name', 1));
    
    

@Harunur Rashid 2018-05-30 09:21:19

Way 1 :

You can use Underscore.js. Import underscore first.

 import * as _ from 'underscore';
 let SortedObjs = _.sortBy(objs, 'last_nom');

Way 2 : Use compare function.

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

objs.sort(compare);

@0leg 2018-06-04 15:24:36

As of 2018 there is a much shorter and elegant solution. Just use. Array.prototype.sort().

Example:

var items = [
  { name: 'Edward', value: 21 },
  { name: 'Sharpe', value: 37 },
  { name: 'And', value: 45 },
  { name: 'The', value: -12 },
  { name: 'Magnetic', value: 13 },
  { name: 'Zeros', value: 37 }
];

// sort by value
items.sort(function (a, b) {
  return a.value - b.value;
});

@smcstewart 2018-06-18 10:02:18

In the question strings were used for comparison as opposed to numbers. Your answer works great for sorting by numbers, but isn't so good for comparisons by string.

@0leg 2019-03-26 09:10:16

The a.value - b.value used to compare the object's attributes (numbers in this case) can be adopted for the various times of data. For example, regex can be used to compare each pair of the neighboring strings.

@Bob Stein 2019-03-28 11:30:04

@0leg I'd like to see an example here of using regex to compare strings in this way.

@Francois Girard 2018-05-28 19:54:49

A simple function that sort an array of object by a property

function sortArray(array, property, direction) {
    direction = direction || 1;
    array.sort(function compare(a, b) {
        let comparison = 0;
        if (a[property] > b[property]) {
            comparison = 1 * direction;
        } else if (a[property] < b[property]) {
            comparison = -1 * direction;
        }
        return comparison;
    });
    return array; // Chainable
}

Usage:

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

sortArray(objs, "last_nom"); // Asc
sortArray(objs, "last_nom", -1); // Desc

@karthik006 2018-03-26 05:40:06

Using lodash or Underscore, its a piece of cake

> const sortedList = _.orderBy(objs, [last_nom], [asc]); // asc or desc

@Bob Stein 2018-02-24 00:54:56

Given the original example:

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

Sort by multiple fields:

objs.sort(function(left, right) {
    var last_nom_order = left.last_nom.localeCompare(right.last_nom);
    var first_nom_order = left.first_nom.localeCompare(right.first_nom);
    return last_nom_order || first_nom_order;
});

Notes

  • a.localeCompare(b) is universally supported and returns -1,0,1 if a<b,a==b,a>b respectively.
  • || in the last line gives last_nom priority over first_nom.
  • Subtraction works on numeric fields: var age_order = left.age - right.age;
  • Negate to reverse order, return -last_nom_order || -first_nom_order || -age_order;

@sg28 2017-08-27 10:26:42

I will give you a solution implementing selectionSort algorithm ,it is simple and effective

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


function selection_Sort(num) { 
 //console.log(num);  
 var temp, index;
 for (var i = 0; i <= num.length - 1; i++) {
index = i;
for (var j = i + 1; j <= num.length - 1; j++) {
 // you can use first_nom/last_nom,any way you choose to sort

  if (num[j]. last_nom < num[index]. last_nom) {
    index = j;
  } 
}

//below is the swapping part
temp = num[i]. last_nom;
num[i]. last_nom = num[index]. last_nom;
num[index]. last_nom = temp;
 };
 console.log(num); 
 return num; 
  }
  selection_Sort(objs);

Great to see such great answers

@Nico Van Belle 2017-08-30 14:15:44

Lodash.js (superset of Underscore.js)

It's good not to add a framework for every simple piece of logic, but relying on a well tested utility frameworks, speed up development and reduce the amount of bugs written is no shame.

Lodash produces very clean code and promotes a more functional programming style, which results in less bugs. In one glimpse it becomes clear what the intent if the code is.

OP's issue can simply be solved as:

const sortedObjs = _.sortBy(objs, 'last_nom');

More info? E.g. we have following nested object:

const users = [
  { 'user': {'name':'fred', 'age': 48}},
  { 'user': {'name':'barney', 'age': 36 }},
  { 'user': {'name':'wilma'}},
  { 'user': {'name':'betty', 'age': 32}}
];

We now can use the _.property shorthand user.age to specify the path to the property that should be matched. We will sort the user objects by the nested age property. Yes, it allows for nested property matching!

const sortedObjs = _.sortBy(users, ['user.age']);

Want it reversed? No problem. Use _.reverse.

const sortedObjs = _.reverse(_.sortBy(users, ['user.age']));

Want to combine both using Chaining instead?

const sortedObjs = _.chain(users).sortBy('user.age').reverse().value();

@Damjan Pavlica 2017-10-20 12:10:40

I have a piece of code that works for me:

arr.sort((a, b) => a.name > b.name)

UPDATE: Not working always, so it is not correct :(

@TitanFighter 2018-02-03 19:55:05

It works, but the result is unstable for some reason

@AO17 2018-02-15 16:43:41

use '-' instead of '>'. That will work.

@Patrick Roberts 2018-07-18 09:23:04

@AO17 no it won't. You can't subtract strings.

@Jean-François Beauchamp 2018-08-29 15:33:21

This should do it: arr.sort((a, b) => a.name < b.name ? -1 : (a.name > b.name ? 1 : 0))

@Ahsan 2019-01-22 13:49:26

@Jean-FrançoisBeauchamp, your solution works perfectly fine and much better.

@Sridhar Sg 2017-07-05 07:43:55

Using Ramda,

npm install ramda

import R from 'ramda'
var objs = [ 
    { first_nom: 'Lazslo', last_nom: 'Jamf'     },
    { first_nom: 'Pig',    last_nom: 'Bodine'   },
    { first_nom: 'Pirate', last_nom: 'Prentice' }
];
var ascendingSortedObjs = R.sortBy(R.prop('last_nom'), objs)
var descendingSortedObjs = R.reverse(ascendingSortedObjs)

@Partha Roy 2016-12-09 14:55:33

So here is one sorting algorithm which can sort in any order , throughout array of any kind of objects , without the restriction of datatype comparison ( i.e. Number , String )

function smoothSort(items,prop,reverse) {  
    var length = items.length;
    for (var i = (length - 1); i >= 0; i--) {
        //Number of passes
        for (var j = (length - i); j > 0; j--) {
            //Compare the adjacent positions
            if(reverse){
              if (items[j][prop] > items[j - 1][prop]) {
                //Swap the numbers
                var tmp = items[j];
                items[j] = items[j - 1];
                items[j - 1] = tmp;
            }
            }

            if(!reverse){
              if (items[j][prop] < items[j - 1][prop]) {
                  //Swap the numbers
                  var tmp = items[j];
                  items[j] = items[j - 1];
                  items[j - 1] = tmp;
              }
            }
        }
    }

    return items;
}
  • the first argument items is the array of objects ,

  • prop is the key of the object on which you want to sort ,

  • reverse is a boolean parameter which on being true results in Ascending order and in false it returns descending order.

@a8m 2016-11-06 13:18:26

I know this question is too old, but I didn't see any implementation similar to mine.
This version is based on the Schwartzian transform idiom.

function sortByAttribute(array, ...attrs) {
  // generate an array of predicate-objects contains
  // property getter, and descending indicator
  let predicates = attrs.map(pred => {
    let descending = pred.charAt(0) === '-' ? -1 : 1;
    pred = pred.replace(/^-/, '');
    return {
      getter: o => o[pred],
      descend: descending
    };
  });
  // schwartzian transform idiom implementation. aka: "decorate-sort-undecorate"
  return array.map(item => {
    return {
      src: item,
      compareValues: predicates.map(predicate => predicate.getter(item))
    };
  })
  .sort((o1, o2) => {
    let i = -1, result = 0;
    while (++i < predicates.length) {
      if (o1.compareValues[i] < o2.compareValues[i]) result = -1;
      if (o1.compareValues[i] > o2.compareValues[i]) result = 1;
      if (result *= predicates[i].descend) break;
    }
    return result;
  })
  .map(item => item.src);
}

Here's an example how to use it:

let games = [
  { name: 'Pako',              rating: 4.21 },
  { name: 'Hill Climb Racing', rating: 3.88 },
  { name: 'Angry Birds Space', rating: 3.88 },
  { name: 'Badland',           rating: 4.33 }
];

// sort by one attribute
console.log(sortByAttribute(games, 'name'));
// sort by mupltiple attributes
console.log(sortByAttribute(games, '-rating', 'name'));

@depiction 2016-09-09 01:48:46

This will sort a two level nested array by the property passed to it in alpha numeric order.

function sortArrayObjectsByPropAlphaNum(property) {
    return function (a,b) {
        var reA = /[^a-zA-Z]/g;
        var reN = /[^0-9]/g;
        var aA = a[property].replace(reA, '');
        var bA = b[property].replace(reA, '');

        if(aA === bA) {
            var aN = parseInt(a[property].replace(reN, ''), 10);
            var bN = parseInt(b[property].replace(reN, ''), 10);
            return aN === bN ? 0 : aN > bN ? 1 : -1;
        } else {
            return a[property] > b[property] ? 1 : -1;
        }
    };
}

Usage:

objs.sort(utils.sortArrayObjectsByPropAlphaNum('last_nom'));

@Luke Schoen 2016-07-09 05:38:03

// Sort Array of Objects

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

// Property to Sort By
var args = "last_nom";

// Function to Sort the Data by given Property
function sortByProperty(property) {
    return function (a, b) {
        var sortStatus = 0,
            aProp = a[property].toLowerCase(),
            bProp = b[property].toLowerCase();
        if (aProp < bProp) {
            sortStatus = -1;
        } else if (aProp > bProp) {
            sortStatus = 1;
        }
        return sortStatus;
    };
}

// Implementation
var sortedArray = booksArray.sort(sortByProperty(args));

console.log("sortedArray: " + JSON.stringify(sortedArray) );

Console log output:

"sortedArray: 
[{"first_nom":"Pig","last_nom":"Bodine"},
{"first_nom":"Lazslo","last_nom":"Jamf"},
{"first_nom":"Pirate","last_nom":"Prentice"}]"

Adapted based on this source: http://www.levihackwith.com/code-snippet-how-to-sort-an-array-of-json-objects-by-property/

@Ravshan Samandarov 2016-06-26 09:10:05

One more option:

var someArray = [...];

function generateSortFn(prop, reverse) {
    return function (a, b) {
        if (a[prop] < b[prop]) return reverse ? 1 : -1;
        if (a[prop] > b[prop]) return reverse ? -1 : 1;
        return 0;
    };
}

someArray.sort(generateSortFn('name', true));

sorts ascending by default.

@Ravshan Samandarov 2016-12-01 12:37:39

Slightly changed version for sorting by multiple fields is here if needed: stackoverflow.com/questions/6913512/…

@Tero Tolonen 2016-05-05 11:36:14

There are many good answers here, but I would like to point out that they can be extended very simply to achieve a lot more complex sorting. The only thing you have to do is to use the OR operator to chain comparision functions like this:

objs.sort((a,b)=> fn1(a,b) || fn2(a,b) || fn3(a,b) )

Where fn1, fn2, ... are the sort functions which return [-1,0,1]. This results in "sorting by fn1", "sorting by fn2" which is pretty much equal to ORDER BY in SQL.

This solution is based on the behaviour of || operator which evaluates to the first evaluated expression which can be converted to true.

The simplest form has only one inlined function like this:

// ORDER BY last_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) )

Having two steps with last_nom,first_nom sort order would look like this:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> a.last_nom.localeCompare(b.last_nom) || 
                  a.first_nom.localeCompare(b.first_nom)  )

A generic comparision function could be something like this:

// ORDER BY <n>
let cmp = (a,b,n)=>a[n].localeCompare(b[n])

This function could be extended to support numeric fields, case sensitity, arbitary datatypes etc.

You can them use it with chaining them by sort priority:

// ORDER_BY last_nom, first_nom
objs.sort((a,b)=> cmp(a,b, "last_nom") || cmp(a,b, "first_nom") )
// ORDER_BY last_nom, first_nom DESC
objs.sort((a,b)=> cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )
// ORDER_BY last_nom DESC, first_nom DESC
objs.sort((a,b)=> -cmp(a,b, "last_nom") || -cmp(a,b, "first_nom") )

The point here is that pure JavaScript with functional approach can take you a long way without external libraries or complex code. It is also very effective, since no string parsing have to be done

@eljefedelrodeodeljefe 2015-08-10 15:52:38

Sorting (more) Complex Arrays of Objects

Since you probably encounter more complex data structures like this array, I would expand the solution.

TL;DR

Are more pluggable version based on @ege-Özcan's very lovely answer.

Problem

I encountered the below and couldn't change it. I also did not want to flatten the object temporarily. Nor did I want to use underscore / lodash, mainly for performance reasons and the fun to implement it myself.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

Goal

The goal is to sort it primarily by People.Name.name and secondarily by People.Name.surname

Obstacles

Now, in the base solution uses bracket notation to compute the properties to sort for dynamically. Here, though, we would have to construct the bracket notation dynamically also, since you would expect some like People['Name.name'] would work - which doesn't.

Simply doing People['Name']['name'], on the other hand, is static and only allows you to go down the n-th level.

Solution

The main addition here will be to walk down the object tree and determine the value of the last leaf, you have to specify, as well as any intermediary leaf.

var People = [
   {Name: {name: "Name", surname: "Surname"}, Middlename: "JJ"},
   {Name: {name: "AAA", surname: "ZZZ"}, Middlename:"Abrams"},
   {Name: {name: "Name", surname: "AAA"}, Middlename: "Wars"}
];

People.sort(dynamicMultiSort(['Name','name'], ['Name', '-surname']));
// Results in...
// [ { Name: { name: 'AAA', surname: 'ZZZ' }, Middlename: 'Abrams' },
//   { Name: { name: 'Name', surname: 'Surname' }, Middlename: 'JJ' },
//   { Name: { name: 'Name', surname: 'AAA' }, Middlename: 'Wars' } ]

// same logic as above, but strong deviation for dynamic properties 
function dynamicSort(properties) {
  var sortOrder = 1;
  // determine sort order by checking sign of last element of array
  if(properties[properties.length - 1][0] === "-") {
    sortOrder = -1;
    // Chop off sign
    properties[properties.length - 1] = properties[properties.length - 1].substr(1);
  }
  return function (a,b) {
    propertyOfA = recurseObjProp(a, properties)
    propertyOfB = recurseObjProp(b, properties)
    var result = (propertyOfA < propertyOfB) ? -1 : (propertyOfA > propertyOfB) ? 1 : 0;
    return result * sortOrder;
  };
}

/**
 * Takes an object and recurses down the tree to a target leaf and returns it value
 * @param  {Object} root - Object to be traversed.
 * @param  {Array} leafs - Array of downwards traversal. To access the value: {parent:{ child: 'value'}} -> ['parent','child']
 * @param  {Number} index - Must not be set, since it is implicit.
 * @return {String|Number}       The property, which is to be compared by sort.
 */
function recurseObjProp(root, leafs, index) {
  index ? index : index = 0
  var upper = root
  // walk down one level
  lower = upper[leafs[index]]
  // Check if last leaf has been hit by having gone one step too far.
  // If so, return result from last step.
  if (!lower) {
    return upper
  }
  // Else: recurse!
  index++
  // HINT: Bug was here, for not explicitly returning function
  // https://stackoverflow.com/a/17528613/3580261
  return recurseObjProp(lower, leafs, index)
}

/**
 * Multi-sort your array by a set of properties
 * @param {...Array} Arrays to access values in the form of: {parent:{ child: 'value'}} -> ['parent','child']
 * @return {Number} Number - number for sort algorithm
 */
function dynamicMultiSort() {
  var args = Array.prototype.slice.call(arguments); // slight deviation to base

  return function (a, b) {
    var i = 0, result = 0, numberOfProperties = args.length;
    // REVIEW: slightly verbose; maybe no way around because of `.sort`-'s nature
    // Consider: `.forEach()`
    while(result === 0 && i < numberOfProperties) {
      result = dynamicSort(args[i])(a, b);
      i++;
    }
    return result;
  }
}

Example

Working example on JSBin

@Tero Tolonen 2016-05-03 16:02:05

Why? This is not the answer to original question and "the goal" could be solved simply with People.sort((a,b)=>{ return a.Name.name.localeCompare(b.Name.name) || a.Name.surname.localeCompare(b.Name.surname) })

@jmwierzbicki 2016-03-16 14:01:55

I came into problem of sorting array of objects, with changing priority of values, basically I want to sort array of peoples by their Age, and then by surname - or just by surname, name. I think that this is most simple solution compared to another answers.

it' is used by calling sortPeoples(['array', 'of', 'properties'], reverse=false)

///////////////////////example array of peoples ///////////////////////

var peoples = [
    {name: "Zach", surname: "Emergency", age: 1},
    {name: "Nancy", surname: "Nurse", age: 1},
    {name: "Ethel", surname: "Emergency", age: 1},
    {name: "Nina", surname: "Nurse", age: 42},
    {name: "Anthony", surname: "Emergency", age: 42},
    {name: "Nina", surname: "Nurse", age: 32},
    {name: "Ed", surname: "Emergency", age: 28},
    {name: "Peter", surname: "Physician", age: 58},
    {name: "Al", surname: "Emergency", age: 58},
    {name: "Ruth", surname: "Registration", age: 62},
    {name: "Ed", surname: "Emergency", age: 38},
    {name: "Tammy", surname: "Triage", age: 29},
    {name: "Alan", surname: "Emergency", age: 60},
    {name: "Nina", surname: "Nurse", age: 58}
];



//////////////////////// Sorting function /////////////////////
function sortPeoples(propertyArr, reverse) {
        function compare(a,b) {
            var i=0;
            while (propertyArr[i]) {
                if (a[propertyArr[i]] < b[propertyArr[i]])  return -1;
                if (a[propertyArr[i]] > b[propertyArr[i]])  return 1;
                i++;
            }
            return 0;
            }
        peoples.sort(compare);
        if (reverse){
            peoples.reverse();
        }
    };

////////////////end of sorting method///////////////
function printPeoples(){
  $('#output').html('');
peoples.forEach( function(person){
 $('#output').append(person.surname+" "+person.name+" "+person.age+"<br>");
} )
}
<head>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
</head>
  <html>
  <body>
<button onclick="sortPeoples(['surname']); printPeoples()">sort by ONLY by surname ASC results in mess with same name cases</button><br>
<button onclick="sortPeoples(['surname', 'name'], true); printPeoples()">sort by surname then name DESC</button><br>
<button onclick="sortPeoples(['age']); printPeoples()">sort by AGE ASC. Same issue as in first case</button><br>
<button onclick="sortPeoples(['age', 'surname']); printPeoples()">sort by AGE and Surname ASC. Adding second field fixed it.</button><br>
        
    <div id="output"></div>
    </body>
  </html>

@RaisingAgent 2017-02-14 14:17:59

array of peoples :(

@David Morrow 2012-05-10 21:24:32

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' }
];

var sortedObjs = _.sortBy( objs, 'first_nom' );

@Jess 2014-01-09 04:01:06

David, could you edit the answer to say, var sortedObjs = _.sortBy( objs, 'first_nom' );. objs will not be sorted itself as a result of this. The function will return a sorted array. That would make it more explicit.

@Erdal G. 2016-01-31 10:43:07

To reverse sort: var reverseSortedObjs = _.sortBy( objs, 'first_nom' ).reverse();

@and-bri 2017-05-29 18:28:54

you need to load the javascript libary "underscore": <script src="http://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8‌​.3/underscore-min.js‌​"> </script>

@WoJ 2018-04-17 10:49:32

Also available in Lodash for the ones who prefer that one

@Travis Heeter 2018-11-15 19:10:03

In lodash this would be the same: var sortedObjs = _.sortBy( objs, 'first_nom' ); or if you want it in a different order: var sortedObjs = _.orderBy( objs, ['first_nom'],['dsc'] );

@Roshni Bokade 2016-03-08 09:51:36

objs.sort(function(a,b){return b.last_nom>a.last_nom})

@madprops 2017-02-21 11:15:32

Actually it didn't seem to work, had to use the accepted answer. It wasn't sorting correctly.

Related Questions

Sponsored Content

41 Answered Questions

[SOLVED] How do I remove a property from a JavaScript object?

88 Answered Questions

[SOLVED] How do I remove a particular element from an array in JavaScript?

  • 2011-04-23 22:17:18
  • Walker
  • 6151028 View
  • 7677 Score
  • 88 Answer
  • Tags:   javascript arrays

47 Answered Questions

[SOLVED] How to check if an object is an array?

21 Answered Questions

[SOLVED] How to sort an array of integers correctly

28 Answered Questions

[SOLVED] Sorting an array of objects by property values

19 Answered Questions

[SOLVED] Storing Objects in HTML5 localStorage

47 Answered Questions

3 Answered Questions

33 Answered Questions

[SOLVED] For-each over an array in JavaScript?

34 Answered Questions

[SOLVED] How do I sort a dictionary by value?

Sponsored Content