1

I know that javascript objects have no inherent order for the key/value pairs it contains, but I have run into an interesting problem, and hopefully, someone can point me to a solution.

I'm developing an angular app that needs to iterate through an array of objects and display the value for a given key in the UI. This is tabular data. Pretty basic. The problem comes from the backend data sources. The data is aggregated from multiple sources, and not all objects get all key/values. We have no control over the backend. Furthermore, there are a variable number of key/value pairs. So, what I get on the frontend may look look like this:

[{ A: a, B: b, C: c}, {B: b, C: c}]

I can iterate the returned array and add missing keys, but things may be out of order, i.e.:

[{ A: a, B: b, C:c}, {B: b, C: c, A: a}]

which, course leads to an incorrect display of data.

for(var val of dataArray){
        for(var header of headers){
            val.environmentMetrics[header] = val.environmentMetrics[header] || 0;
        }
    }

headers is an array of strings that match the keys. The first object in the returned data contains the keys, which are used for the table headers.

So whats the best way to get my data order consistently? Thanks

Lazloman
  • 1,289
  • 5
  • 25
  • 50
  • Sort the key names? – SLaks Dec 12 '16 at 16:00
  • *"I know that javascript objects have no inherent order for the key/value pairs it contains"* That's no longer true, as of ES2015. But relying on that order still isn't a good idea, and wouldn't help you with this problem. :-) – T.J. Crowder Dec 12 '16 at 16:01
  • @T.J.Crowder It is still true. `for .. in` has a well-defined iteration order and `Object.keys()` is guaranteed to return the keys in that same well-defined order, but the object itself still has no order. – Paul Dec 12 '16 at 16:10
  • @Paulpro: Actually, that's exactly backward. :-) Object properties have an order, but `for-in` and `Object.keys` **don't** have any guarantee that they follow the order. Only new operations like `Object.getOwnPropertyNames` and such have that guarantee. The order from `for-in` and `Object.keys` remains unspecified, other than that they must match each other (for enumerable properties). See: http://stackoverflow.com/questions/30076219/does-es6-introduce-a-well-defined-order-of-enumeration-for-object-properties – T.J. Crowder Dec 12 '16 at 16:22
  • @T.J.Crowder Yeah, I had that backwards, `Object.getOwnPropertyNames` is the one that has a well-defined order; I would still say that object properties don't have an order though. – Paul Dec 12 '16 at 16:31
  • @Paulpro: :-) Yeah, it's almost a semantic point, or even an implementation detail, whether they "have order" or just have operations that apply an order. – T.J. Crowder Dec 12 '16 at 16:36

1 Answers1

4

I'd probably use Object.keys and sort the result in the order you want them to be in, then loop through that array to do the output.

It's not clear to me from your question whether you're talking about dataArray or headers, so just in the abstract:

var obj = {
  c: "see",
  a: "ay",
  b: "bee",
  d: "dee"
};
console.log("Object order:");
var key, keys = [];
for (key in obj) {
  keys.push(key);
}
console.log(keys.map(function(key) { return key + ": " + obj[key];}).join(", "));

console.log("Sorted order:");
keys = Object.keys(obj).sort()
console.log(keys.map(function(key) { return key + ": " + obj[key];}).join(", "));
T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
  • Thanks, this helped quite a bit, I ended up with a string of key/value pairs which I was able to coerce into an the object I was looking for, – Lazloman Dec 12 '16 at 20:29