views:

853

answers:

3

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

I'm having a real brain-dead moment regarding this.

+4  A: 

Why would you want to do that? AFAIK, the order of an object's properties is undefined, so reordering is something that theoretically can't be done.

Philippe Leybaert
I want to end up with an ordered list of players that allows me to know who is next to execute a command (where lower int values should move before higher int values).
Steerpike
See http://ejohn.org/blog/javascript-in-chrome/ (for loop order). I think what he wants to do can be done. But shouldn't.
Nosredna
+8  A: 

JavaScript objects are unordered by definition (see the ECMAScript Language Specification, section 8.6). The language specification doesn't even guarantee that, if you iterate over the properties of an object twice in succession, they'll come out in the same order the second time.

If you need things to be ordered, use an array and the Array.prototype.sort method.

NickFitz
Note that's there's been quite a bit of arguing about this. Most implementations keep the list in the order in which elements were added. IIRC, Chrome doesn't. There was argument about whether Chrome should fall in line with the other implementations. My belief is that a JavaScript object is a hash and no order should be assumed. I believe Python went through the same argument and a new ordered hash-like list was recently introduced. For most browsers, you CAN do what you want by recreating your object, adding elements by sorted value. But you shouldn't.
Nosredna
Edit. Chrome usually keeps order, but doesn't always. And here's the relevant Chromium bug: http://code.google.com/p/chromium/issues/detail?id=883
Nosredna
That bug report is unjustified, and those who relied on the undocumented behaviour are the ones with the bugs. Read ECMASCript section 8.6; it clearly states that "An Object is an unordered collection of properties". Anybody who found that it didn't seem that way in a few implementations, and then started to depend on that implementation-specific behaviour,made a big mistake, and they shouldn't be trying to shift the blame away from themselves. If I was on the Chrome team I'd mark that bug report as "Invalid, WontFix".
NickFitz
But why would Chrome want to break on pages that work on other browsers? I agree with your sentiment, though. Should not rely on order.
Nosredna
EcmaScript 5 actually defines the order of enumeration to be the order of insertion -- the absence of definition is considered a spec bug in ES3.It's worth noting that the EcmaScript spec defines behaviour that no one would consider sane -- for example spec behaviour is that syntax errors are in many cases thrown at runtime, incorrect use of continue, break, ++, --, const, etc according to the spec any engine that throws an exception before reaching that code is *wrong*
olliej
+3  A: 

Move them to an array, sort that array, and then use that array for your purposes.

Here's a solution I found via Google.


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.

Nosredna