1

I am stuck with an object structure (for now) that I would like to see if I can try to sort. My object looks like this right now -

{
  "type1" : { 
    "position": 3
  },
  "type2" : { 
     "position": 1
  }
}

And what I am trying to figure out is if there is a way to re order (sort) the object keys/values but that nested position. So the desired outcome would be

{
  "type2" : { 
     "position": 1
  },
  "type1" : { 
    "position": 3
  }
}

So what would determine the order is that position value in the object. I am refactoring another project to try an add some sorting to this list. I know it would be much easier if it were a list of objects, but this would require me to change quite a lot of other code so I am trying to find out if I can keep the object structure as is (if possible of course). Thanks for reading!

ajmajmajma
  • 11,766
  • 18
  • 67
  • 124
  • 4
    [Object keys do *not* have an ordering](https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order). Any ordering you do see is purely implementation defined. – Phylogenesis Aug 14 '17 at 13:09
  • 1
    Object properties are by definition unordered, so this is not possible. You need to make it into an array if the order is important – Lennholm Aug 14 '17 at 13:10
  • Cool, thanks for the answer guys. I will just close this since it's a dupe – ajmajmajma Aug 14 '17 at 13:14
  • 1
    What you *can* do, however, is something like: `Object.keys(myObj).sort((a, b) => myObj[a].position - myObj[b].position)`, to get an array of keys in your preferred ordering. – Phylogenesis Aug 14 '17 at 13:16

1 Answers1

1

var a = {
  "type1" : { 
    "position": 3
  },
  "type2" : { 
     "position": 1
  }
};

var b = Object.assign(
    ...Object
    .keys(a)
    .sort((x, y) => a[x].position >= a[y].position)
    .map(k => ({ [k]: a[k] }))
);

console.log (b);
qiAlex
  • 3,794
  • 2
  • 11
  • 30
  • 1
    This doesn't work as it still relies on implementation-defined ordering of keys. Chrome recently changed their own implementation, for example, that broke expected ordering in some web apps. – Phylogenesis Aug 14 '17 at 13:23
  • Can you clarify your comment? in my answer objects `a` and `b` are ordering differently. And there was no clarification should it be a new object or reordering of existing. And there was no browser, or ES version specified in question. So why do you talking, that this answer is not cover all cases while no case was specified? – qiAlex Aug 14 '17 at 13:37
  • The ordering returned is implementation defined. You are expecting it to keep insertion order, but this is not guaranteed in ECMAScript and is definitively not always the case in at least Chrome and Edge. When I run your snippet in Edge, for instance, I see `type1` followed by `type2`. – Phylogenesis Aug 14 '17 at 14:02
  • Well, When I run it on ie6 it throws an error, and what? this option is documented in ECMAScript and browser support is another big question. big question that was not specified. Who knows may be ajmajmajma wants to use it in typescript or with babel. – qiAlex Aug 14 '17 at 14:23
  • @qiAlex I am using babel! would this be a safe bet if I am? – ajmajmajma Aug 14 '17 at 15:41
  • 1
    yes, i'm 99% sure that it will – qiAlex Aug 14 '17 at 15:44
  • How is it documented? It's precisely documented to say that the ordering is **not defined**: See page 373 (section 13.7.5.15) of the [specification](https://www.ecma-international.org/publications/files/ECMA-ST/Ecma-262.pdf). Relying on this behaviour makes your code susceptible to breaking in the future if/when a browser decides to change their implementation (as Chrome has done in the past). – Phylogenesis Aug 14 '17 at 16:05
  • Thank you for the discussion - I am going to swap it to an array and make a small model in between so I don't have to change much code. – ajmajmajma Aug 14 '17 at 16:13
  • https://jsfiddle.net/77tjqa5L - just check this. ordering will work properly. – qiAlex Aug 14 '17 at 16:25
  • You quoted the wrong bit of that section. Here's the correct quote: *The mechanics and order of enumerating the properties is not specified but must conform to the rules specified below.* In other words, any ordering you get back is implementation defined and is not a guarantee. As I stated before, Microsoft Edge *does not adhere to insertion order*, and that is perfectly valid according to the specification. Any browser is able to arbitrarily change their ordering and *you cannot rely on any current implementation*. – Phylogenesis Aug 14 '17 at 16:36
  • Ok, just clarify something for me please. what exact line in my answer that is not stable? – qiAlex Aug 14 '17 at 16:46
  • The `Object.assign()` bit. Just because you add the keys in a certain order, it does not mean that any implementation has to enumerate the properties in that order. There is no defined ordering of keys in an `Object` and an implementation would still be perfectly valid if it enumerated them alphabetically, or if it ordered them based on how far the third character of the key is from the codepoint `U+0070`. The whole point is the specification says the ordering of keys is not specified means that you cannot rely on the fact that some implementations return keys in insertion order. – Phylogenesis Aug 15 '17 at 07:34
  • ok, may be you mean this situation: https://jsfiddle.net/77tjqa5L/2/ – qiAlex Aug 15 '17 at 10:51
  • Just because it happens to work right now, it doesn't make it *correct*. As there's no specification of ordering, relying on an implementation paves the way for your code to break in the future if/when a particular implementation changes. If you want to see the way implementations *already ignore insertion order in certain cases*, look [here](https://jsfiddle.net/h22dve4q/). – Phylogenesis Aug 15 '17 at 13:48