1

I have an object like this

//input
let data={
    "51": {"name": "text51"},
    "54": {"name": "text54"},
    "61": {"name": "text61"},
    "64": {"name": "text64"},
    "71": {"name": "text71"},
    "74": {"name": "text74"},
    "81": {"name": "text81"},
    "84": {"name": "text84"}
}

/*
targeted output
{
    "51": {"name": "text51"},
    "61": {"name": "text61"},
    "71": {"name": "text71"},
    "81": {"name": "text81"},
    "54": {"name": "text54"},
    "64": {"name": "text64"},
    "74": {"name": "text74"},
    "84": {"name": "text84"}
}
*/

I sort it base on the digit of the keys.

new_key=Object.keys(data).sort((a, b)=>parseInt(a.slice(-1)) - parseInt(b.slice(-1)));
//output is ---> ['51', '61', '71', '81', '54', '64', '74', '84']

Now I want to rearrange the object base on the above output. (I did that)

result=new_key.reduce((r, k) => {
    console.log(r);
    r[k] = data[k];
    return r;
}, {});

When I console.log(r) for each iteration I got this:

enter image description here

My question is why when 54 key came it went to the middle of the object instead of going to the end.

Peter Seliger
  • 11,747
  • 3
  • 28
  • 37
Niyaz
  • 797
  • 1
  • 8
  • 18

3 Answers3

3

Object keys order was not guaranteed earlier in JS. Now it is. But here is how it is going to be.

What matters here is for integer like keys, the order will be ascending.

For string keys it is order of insertion, which can be tested by appending a character to the integer every time.

let data={
    "51": {"name": "text51"},
    "54": {"name": "text54"},
    "61": {"name": "text61"},
    "64": {"name": "text64"},
    "71": {"name": "text71"},
    "74": {"name": "text74"},
    "81": {"name": "text81"},
    "84": {"name": "text84"}
};

let new_key=Object.keys(data).sort((a, b)=>parseInt(a.slice(-1)) - parseInt(b.slice(-1)));

let result=new_key.reduce((r, k) => {
    console.log(r);
    r['x-' + k] = data[k];
    return r;
}, {});
Tushar Shahi
  • 16,452
  • 1
  • 18
  • 39
2

You cannot define your own sorting of object keys, as browser (and ES specifications) tend do do their own sorting.

You can find a ton of questions and answers on StackOverflow (a couple examples: ES5, ES6)

If you really care about the order, I would suggest using an array instead.

Balastrong
  • 4,336
  • 2
  • 12
  • 31
1

console.log(
  Object.entries({

    "51": {"name": "text51"},
    "54": {"name": "text54"},
    "61": {"name": "text61"},
    "64": {"name": "text64"},
    "71": {"name": "text71"},
    "74": {"name": "text74"},
    "81": {"name": "text81"},
    "84": {"name": "text84"},

  }).sort(([aKey], [bKey]) => {

    const aInt = parseInt(aKey.split('').reverse().join(''), 10);
    const bInt = parseInt(bKey.split('').reverse().join(''), 10);
    return aInt - bInt;

  }).reduce((result, [key, value]) =>

    // - key insertion prescedence/order is guaranteed since ES6/ES2015.
    //
    // - but is does not apply for pure digit based keys.
    // - insertion of the latter is handled by an ascending key order.
    //
    // ... try ...
    Object.assign(result, { [key]: value }), {}
    // ... versus ...
    // Object.assign(result, { [`_${ key }`]: value }), {}
  )
);
console.log(
  Object.entries({

    "51": {"name": "text51"},
    "54": {"name": "text54"},
    "61": {"name": "text61"},
    "64": {"name": "text64"},
    "71": {"name": "text71"},
    "74": {"name": "text74"},
    "81": {"name": "text81"},
    "84": {"name": "text84"},

  }).sort(([aKey], [bKey]) => {

    const aInt = parseInt(aKey.split('').reverse().join(''), 10);
    const bInt = parseInt(bKey.split('').reverse().join(''), 10);
    return aInt - bInt;

  }).reduce((result, [key, value]) =>

    // - key insertion prescedence/order is guaranteed since ES6/ES2015.
    //
    // - but is does not apply for pure digit based keys.
    // - insertion of the latter is handled by an ascending key order.
    //
    // ... try ...
    // Object.assign(result, { [key]: value }), {}
    // ... versus ...
    Object.assign(result, { [`_${ key }`]: value }), {}
  )
);
.as-console-wrapper { min-height: 100%!important; top: 0; }
Peter Seliger
  • 11,747
  • 3
  • 28
  • 37