Sorting JavaScript Object by Property Value

There is several things we will talk about here. The first is about understanding native sorting numerical values. The second is about sorting numerical values numerically. The third is about sorting alphabetical value. At last, we will see two ways to order JavaScript objects effectively.


Forewords

Before digging into the main matter of this article, I will give some explanations to make clear why I do the things as I do them.

It's told that according to the ECMAScript Language Specification, JavaScript objects are unordered by definition. Personally, I did not succeed to find the information so any help is welcome. The draft evolved since then. The language specification would not even guarantee that, if you iterate over the properties of an object twice in succession, they will come out in the same order the second time. Actually, it is all about engine implementation. There has been quite a bit of arguing about this. Most implementation keep the list in the order in which elements were added. If I remember correctly, Chrome does not. There was an issue for Chrome here. Status: WontFix. Point made.

There is no defacto standard, Chrome (about 20% marketshare), IE (about 50% marketshare) and Firefox (about 35% marketshare) all have quirks that can result in properties having a different order from each other. So when dealing with arbitrary keys on unknown objects in a cross-browser fashion, the order isn't, and never has been, consistent. That is why I suggest you to use array of objects. Be clean, be sure, be everything-proof.

About Native Array Sorting

You may want to sort an array of literal value, using Array.sort() method, such as:

['q', 'w', 'e', 'r', 't', 'y']

If you do so, we will get:

["e", "q", "r", "t", "w", "y"]

This is what you would expect to got. Now, if you try to sort literal numerical value, such as:

['1', '5', '3', '20', '4']

You will get:

["1", "20", "3", "4", "5"]

Actually, it is kind of logic. But you should be aware of this behavior since it might be kinda confusing at first. I don't have any valuable references to support my sayings so I will not deep into any explanations.

Sorting Numerical Values Numerically

If you want to sort literal numerical as integer, here is how you should do:

['1', '5', '3', '20', '4'].sort(function (a, b) { return a - b; });

It works. Trust me. The thing here is that using a string in a binary operation will make JavaScript converts the string into an Integer. If it is possible, then everything goes fine else JavaScript throws an exception NaN.

Let me explain the function given to the sort method.

When you give a function to the sort method, you give what is called an iterator. This determines the sort order through the return value. According to the MDN JavaScript Reference about Array.sort():

  • If the return value is less than 0, then the first element will get a lower index than the second;
  • If the return value is equal to 0, then nothing happens (Note: It seems that this is neither specified in ECMAScript standard, so… F***!);
  • If the return value is greater than 0, then the second element will get a lower index than the first.

So, comparing ['5, '3'] will run 5 - 2, which will return 3, so 3 will get a lower index than 5. At last, we got ['3', '5'] which is relevant since, yes, 3 is less than 5.

Sorting Alphabetical Value

Actually, if you want to sort alphabetical values, you have nothing to do. What you have to do is directly call the sort method and, well, that's all.

['q', 'w', 'e', 'r', 't', 'y'].sort() # => ["e", "q", "r", "t", "w", "y"]

We already saw that previously. Actually, it is exactly one of the previous example. But for the purpose of this article I will detail some things to understand the last part.

Natively, the algorithm used by the sort method to sort alphabetical values is the following:

If a is less than b following some criteria  
  return -1;
If a is greater than b following the same criteria  
  return 1;

return 0;

So, the function to sort strings will be:

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

Now, you can try the following:

['q', 'w', 'e', 'r', 't', 'y'].sort(function (a, b) {  
  if (a < b) {
    return -1;
  } else if (a > b) {
    return 1;
  }
  return 0;
});

You will get the same as the native behavior.

Note: You might want take care of comparison of special characters. To do so, please read the MDN Documentation which explains well enough how to use String.localCompare.

It is time to talk about serious stuff.

Ordering JavaScript Objects Efficiently

There is two kinds of objects we will talk about. And those are the followings:

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

[
  {vehicle: 'car',        velocity: 300},
  {vehicle: 'bike',       velocity: 60},
  {vehicle: 'motorbike',  velocity: 200},
  {vehicle: 'airplane',   velocity: 1000},
  {vehicle: 'helicopter', velocity: 400},
  {vehicle: 'rocket',     velocity: 8*60*60}
];

Actually, the second one is an array of objects but the thing is there is exactly the same data. We will see why I present the second one.

To sort the first object, the thing will be the following:

  • Convert this in an array;
  • Sort the resulted array;
  • Convert the sorted array in an object;

I will show you the two-first steps as the last one is pretty easy when you have your data in hands.

First Case

Convert The Object In Array

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

for (var vehicle in maxSpeed)  
  sortable.push([vehicle, maxSpeed[vehicle]])

Easy, right? Nothing to explain here.

Sort The Sortable Array

According to what I already explained to you, here comes the following:

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

The only thing to have in mind is that a and b are arrays and we want to sort by their second items which correspond to the original object values .

Now, what you have to do is to reconstruct your object from the sorted array. And the job is done!

Build The Final Object

As a gift:

resultObject = new Object();  
for (i = 0, len = sortable.length; i < len; i++) {  
  resultObject[sortable[i][0]] = sortable[i][1];
}

Be careful! As I told you earlier, this might not work in Chrome for example.

Second Case

One might say this case is way to wordy. Well, yes, sure. But it still remains my preferred form. First, it is more descriptive. I know what I am confronting to. Second, the sorting stuff is way easier than the first case. Look:

var maxSpeed = [  
  {vehicle: 'car',        velocity: 300},
  {vehicle: 'bike',       velocity: 60},
  {vehicle: 'motorbike',  velocity: 200},
  {vehicle: 'airplane',   velocity: 1000},
  {vehicle: 'helicopter', velocity: 400},
  {vehicle: 'rocket',     velocity: 8*60*60}
];

maxSpeed.sort(function(a, b) { return a.velocity - b.velocity; });

Verdict?

And if you want to sort string values, you know what to do as I already have explained it to you!

Enjoy!

Feel free to commend