0

I do not understand the arrangement when inserting objects in another object. In this example:

const list = {
    "mainVal": {
    }
}

list['mainVal']['010'] = {"a" : "1"}
list['mainVal']['020'] = {"a" : "1"}
list['mainVal']['021'] = {"a" : "1"}
list['mainVal']['023'] = {"a" : "1"}
list['mainVal']['031'] = {"a" : "1"}
list['mainVal']['032'] = {"a" : "1"}
list['mainVal']['300'] = {"a" : "1"}

Results to:

{
    "mainVal": {
        "300": {
            "a": "1"
        },
        "010": {
            "a": "1"
        },
        "020": {
            "a": "1"
        },
        "021": {
            "a": "1"
        },
        "023": {
            "a": "1"
        },
        "031": {
            "a": "1"
        },
        "032": {
            "a": "1"
        }
    }
}

How come 300 key is on the top of the object now when it has been 'inserted' last? So it is not in chronological order nor alphabetical order.

I checked related questions:

Does JavaScript Guarantee Object Property Order?

Does ES6 introduce a well-defined order of enumeration for object properties?

But both of them talk about arrangement of properties. I am specifically asking about arrangement of keys. And they say that it is either chronological or alphabetical, but this isnt the case here.

How can make it be in alphabetical order (or if that is not possible then can I force it to be in chronological order?):

{
    "mainVal": {
        "010": {
            "a": "1"
        },
        "020": {
            "a": "1"
        },
        "021": {
            "a": "1"
        },
        "023": {
            "a": "1"
        },
        "031": {
            "a": "1"
        },
        "032": {
            "a": "1"
        },
        "300": {
            "a": "1"
        }
    }
}

Can anyone please shed some light? Thanks

keechan
  • 989
  • 6
  • 16

2 Answers2

3

That's because Integer indices came before string indices which then came before Symbols.

300 is an an integer index, whereas 010 is a string index.

Here's a good introduction I've found.

I guess to order them, you have to use Arrays (where you sort them the way you want), or keep it in one type of index. So for example you could convert to strings by prefixing each key with an underscore before inserting them into the object.

Example:

const x = {
    "010": {
        "a": "1"
    },
    "020": {
        "a": "1"
    },
    "021": {
        "a": "1"
    },
    "023": {
        "a": "1"
    },
    "031": {
        "a": "1"
    },
    "032": {
        "a": "1"
    },
    "300": {
        "a": "1"
    }
}

let sorted = Object.keys(x)
    .sort((a, b) => parseInt(a) - parseInt(b))
    .map((key) => ({__key: key, ...x[key]}));


Returns:


[ { __key: '010', a: '1' },
  { __key: '020', a: '1' },
  { __key: '021', a: '1' },
  { __key: '023', a: '1' },
  { __key: '031', a: '1' },
  { __key: '032', a: '1' },
  { __key: '300', a: '1' } ]

Proxy

Better yet, you can use a Proxy (not supported in IE11):

let y = new Proxy(x, {
    ownKeys(target) {
        return Object.keys(target)
            .sort((a, b) => parseInt(a) - parseInt(b))
    }
})

This Proxy will in fact return your desired Object with sorted keys:

{ '010': { a: '1' },
  '020': { a: '1' },
  '021': { a: '1' },
  '023': { a: '1' },
  '031': { a: '1' },
  '032': { a: '1' },
  '300': { a: '1' } }
Felix
  • 1,830
  • 12
  • 18
0

If the properties under mainval is known then just rearrange it through this way. A very close problem I have solved this way few weeks ago. Lets see that exapmle.

const mainVal= new Object(json.mainval); // make mainval object with correct input
mainVal.forEach(obj => {
        obj.300= {};
        obj.010= {};
        obj.020= {};
        obj.021= {};
        obj.023= {};
        obj.031= {};
        //.............add this way
      });
mainVal.map((element) => {
       let keys = Object.keys(new Object(element));
       for (let h = 0; h < keys.length; h++) {

       if (keys[h].startsWith('300')) {
            let st = keys[h];
            let ob = new Object(st);
            element.300= element[ob];
            delete element[ob];
          }
       if (keys[h].startsWith('010')) {
            let st = keys[h];
            let ob = new Object(st);
            element.010 = element[ob];
            delete element[ob];
          }
 }
}

Please rearrange it in your own format. But the concept is same.

Suman Kumar Dash
  • 525
  • 3
  • 16