Categories
javascript object properties sorting

Sorting object property by values

920

If I have a JavaScript object such as:

var list = {
  "you": 100, 
  "me": 75, 
  "foo": 116, 
  "bar": 15
};

Is there a way to sort the properties based on value? So that I end up with

list = {
  "bar": 15, 
  "me": 75, 
  "you": 100, 
  "foo": 116
};

10

  • 4

    Not only “sorting,” but more importantly sorting numbers. Numbers are immune to Javascripts Array.sort() method, meaning you’ll not just have to find a method for sorting properties, but you’ll have to write your own function to compare the numerical values.

    – Sampson

    Jul 1, 2009 at 15:12

  • 202

    Before you read the answers: The answer is No. The ordering of object properties is non-standard in ECMAScript. You should never make assumptions about the order of elements in a JavaScript object. An Object is an unordered collection of properties. The answers below show you how to “use” sorted properties, using the help of arrays, but never actually alter the order of properties of objects themselves. So, no, it’s not possible. Even if you build an object with presorted properties, it is not guaranteed that they will display in the same order in the future. Read on :).

    Oct 29, 2016 at 0:31

  • 9

    @GovindRai yet, in real world frontend applications we loop over object collections with IDs as the keys and the order is important if translated to HTML templates. You say they have no order, I say they have exactly the order that I see when console.logging them in the current browser. And that order can get reordered. As soon as you loop over them, they have an order.

    Dec 19, 2016 at 15:27

  • 9

    @GovindRai: There is now a means of accessing properties in a specified order in the spec. Is it a good idea? Almost certainly not. 🙂 But it’s there, as of ES2015.

    Dec 31, 2016 at 16:22


  • 17

    2019 visitors: check this barely upvoted Object.entries-based answer which is the cleanest and most readable state of the art since ES2017: stackoverflow.com/a/37607084/245966

    – jakub.g

    May 3, 2019 at 22:33


975

Move them to an array, sort that array, and then use that array for your purposes. Here’s a solution:

let maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};
let sortable = [];
for (var vehicle in maxSpeed) {
    sortable.push([vehicle, maxSpeed[vehicle]]);
}

sortable.sort(function(a, b) {
    return a[1] - b[1];
});

// [["bike", 60], ["motorbike", 200], ["car", 300],
// ["helicopter", 400], ["airplane", 1000], ["rocket", 28800]]

Once you have the array, you could rebuild the object from the array in the order you like, thus achieving exactly what you set out to do. That would work in all the browsers I know of, but it would be dependent on an implementation quirk, and could break at any time. You should never make assumptions about the order of elements in a JavaScript object.

let objSorted = {}
sortable.forEach(function(item){
    objSorted[item[0]]=item[1]
})

In ES8, you can use Object.entries() to convert the object into an array:

const maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};

const sortable = Object.entries(maxSpeed)
    .sort(([,a],[,b]) => a-b)
    .reduce((r, [k, v]) => ({ ...r, [k]: v }), {});

console.log(sortable);

In ES10, you can use Object.fromEntries() to convert array to object. Then the code can be simplified to this:

const maxSpeed = {
    car: 300, 
    bike: 60, 
    motorbike: 200, 
    airplane: 1000,
    helicopter: 400, 
    rocket: 8 * 60 * 60
};

const sortable = Object.fromEntries(
    Object.entries(maxSpeed).sort(([,a],[,b]) => a-b)
);

console.log(sortable);

17

  • 25

    Can you please reformulate “you can rebuild” to “you can use array to maintain ordering of keys and pull values from object”? Not only it is non-standard, as you’ve yourself mentioned, this erroneous assumption is broken by more browsers than just Chrome today, so it’s better not to encourage users to try it.

    Aug 15, 2012 at 15:42

  • 34

    Here is a more compact version of your code. Object.keys(maxSpeed).sort(function(a, b) {return -(maxSpeed[a] – maxSpeed[b])});

    – TheBrain

    Sep 12, 2012 at 11:07


  • 6

    @TheBrain: Just to add, keys() is only supported by IE9+ (and other modern browsers), if that is of concern. Also keys() excludes enumerable properties from the elements prototype chain (unlike for..in) – but that is usually more desirable.

    – MrWhite

    Nov 28, 2012 at 9:07

  • 31

    _.pairs turns an object into [ [key1, value1], [key2, value2] ]. Then call sort on that. Then call _.object on it to turn it back.

    – dansch

    Feb 20, 2014 at 14:45

  • 2

    My project requires object keys for merging cleanly, but also requires explicit sorting as the metadata drives UI. I followed a similar approach only I added a hasOwnProperty check to avoid crawling up the prototype chain. Here’s a good article on iterating over object properties in JS hackernoon.com/…

    Mar 1, 2019 at 22:46


496

We don’t want to duplicate the entire data structure, or use an array where we need an associative array.

Here’s another way to do the same thing as bonna:

var list = {"you": 100, "me": 75, "foo": 116, "bar": 15};
keysSorted = Object.keys(list).sort(function(a,b){return list[a]-list[b]})
console.log(keysSorted);     // bar,me,you,foo

13

  • 31

    This seems to be sorting by key, not value, which is not what the question called for?

    – Michael

    Jan 7, 2015 at 4:26

  • 39

    It’s sorted by value, and displays keys — but we lose the value count when it prints out, as it prints only keys.

    – Hanna

    Jul 22, 2015 at 21:16

  • 8

    Object property order is not guaranteed in JavaScript, so sorting should be done into an array, not an object (which is what you are referring to as an ‘associative array’).

    Nov 6, 2015 at 20:59

  • 8

    Don’t forget. keysSorted is an array! Not an object!

    – Green

    Feb 6, 2017 at 15:14

  • 29

    If you add .map(key => list[key]); to the end of the sort, it will return the whole object instead of just the key

    Jan 10, 2018 at 15:00


235

Your objects can have any amount of properties and you can choose to sort by whatever object property you want, number or string, if you put the objects in an array. Consider this array:

var arrayOfObjects = [   
    {
        name: 'Diana',
        born: 1373925600000, // Mon, Jul 15 2013
        num: 4,
        sex: 'female'
    },
    {

        name: 'Beyonce',
        born: 1366832953000, // Wed, Apr 24 2013
        num: 2,
        sex: 'female'
    },
    {            
        name: 'Albert',
        born: 1370288700000, // Mon, Jun 3 2013
        num: 3,
        sex: 'male'
    },    
    {
        name: 'Doris',
        born: 1354412087000, // Sat, Dec 1 2012
        num: 1,
        sex: 'female'
    }
];

sort by date born, oldest first

// use slice() to copy the array and not just make a reference
var byDate = arrayOfObjects.slice(0);
byDate.sort(function(a,b) {
    return a.born - b.born;
});
console.log('by date:');
console.log(byDate);

sort by name

var byName = arrayOfObjects.slice(0);
byName.sort(function(a,b) {
    var x = a.name.toLowerCase();
    var y = b.name.toLowerCase();
    return x < y ? -1 : x > y ? 1 : 0;
});

console.log('by name:');
console.log(byName);

http://jsfiddle.net/xsM5s/16/

6

  • 1

    Sort by name should not substr out the first character; else Diana and Debra have an undefined order. Also, your byDate sort actually uses num, not born.

    Mar 12, 2014 at 19:55

  • This looks good, but note that to compare strings you can just use x.localeCompare(y)

    Mar 22, 2017 at 15:38

  • 2

    @JemarJones localCompare looks like a very useful function! Just note that it won’t be supported in every browser – IE 10 and less, Safari Mobile 9 and less.

    – inorganik

    Mar 22, 2017 at 17:51

  • @inorganik Yes very good note for those who need to support those browsers

    Mar 23, 2017 at 18:44

  • 1

    This is an array of Objects, which is not the OP asked for (an Object with several properties)

    Apr 15, 2018 at 19:36