1

I have an object

{
1: {id: 1, first: 1, last: 5}
2: {id: 2, first: 6, last: 10}
3: {id: 3, first: 11, last: 15}
}

I need to reverse the items order without sorting the keys so the final result is:

{
1: {id: 3, first: 11, last: 15}
2: {id: 2, first: 6, last: 10}
3: {id: 1, first: 1, last: 5}
}

Is this possible?

I tried to convert it into array and then into an object but the new object starts with key 0 while I need it to start with key 1:

let array = [];
Object.values(this.props.items)
.sort()
.reverse()
.forEach(function(b) {
    array.push(b);
});

const newItems = Object.assign({}, array);

// Result:
{
0: {id: 3, first: 11, last: 15}
1: {id: 2, first: 6, last: 10}
2: {id: 1, first: 1, last: 5}
}

EDIT

Worth mention that my object is typed:

Btw this.props.items is typed TypeScript object eg. Section.Item[]

nickornotto
  • 1,466
  • 2
  • 29
  • 55
  • 2
    You might want to look into [Does JavaScript Guarantee Object Property Order?](https://stackoverflow.com/questions/5525795/does-javascript-guarantee-object-property-order) – palaѕн May 01 '20 at 14:50
  • `let array = [{}];` Start off with an element in position 0, then, `delete newItems[0];`. – Heretic Monkey May 01 '20 at 15:06
  • @palaѕн N.B. that this OP wants to shuffle which values are stored under keys `1`, `2`, and `3`, rather than sort the keys themselves. – apsillers May 01 '20 at 15:07

3 Answers3

2

You could get keys and values and assign the popped value to the keys.

var object = { 1: { id: 1, first: 1, last: 5 }, 2: { id: 2, first: 6, last: 10 }, 3: { id: 3, first: 11, last: 15 } },
    values = Object.values(object)

Object.keys(object).forEach(k => object[k] = values.pop());

console.log(object);
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
  • I'm thinking of deleting my answer since you cant reverse the order of the values of an object. Documentation of [entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) says `same order as that provided by a for...in` and [for in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) says `iterates over the properties of an object in an arbitrary order` so there is nothing to reverse if there is no set order. Code works by accident but not by design. – HMR May 01 '20 at 16:55
  • 2
    @HMR, objects have a defined order (now). first it takes index like values (positive 32 bit integer values), then all other in insertation order and at last symbols. and yes, you can reverse the order of values. – Nina Scholz May 01 '20 at 16:58
1

You could use fromEntries

const data = {
  1: { id: 1, first: 1, last: 5 },
  2: { id: 2, first: 6, last: 10 },
  3: { id: 3, first: 11, last: 15 },
};
console.log(
  Object.fromEntries(
    Object.values(data)
      .reverse()
      .map((val, index) => [index + 1, val])
  )
);
HMR
  • 30,349
  • 16
  • 67
  • 136
  • @nickornotto Actually; Nina's answer is more precise. If your object has keys like `{2:{},5:{}}` then the reverse would be: `{5:{},2:{}}`. But actually no answer is correct because you can't reverse the keys in an object in JavaScript because the keys of an object are not guaranteed to come in a certain order. – HMR May 01 '20 at 16:33
  • @HMR I'm a little confused by "the keys of an object are not guaranteed to come in a certain order" therefore "no answer is correct" -- indeed keys aren't well-sorted (for at least some operations) but the OP's example in the question doesn't ask for a solution that changes order of keys, but for a solution that shuffles the values under keys (still in the same 1,2,3 order as pre-transformation). It seems you *do* have a fine answer already. Or am I misreading the OP's example input/output? – apsillers May 01 '20 at 16:45
  • @apsillers You are correct, OP asked to reverse values. If you have an object like `{1:val1,2:val2}` then there is no order of `val1` and `val2` so you can't reverse them. Documentation of [entries](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/entries) says `same order as that provided by a for...in` and [for in](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for...in) says `iterates over the properties of an object in an arbitrary order` so there is nothing to reverse if there is no set order. – HMR May 01 '20 at 16:48
  • @HMR I imagine other answers may also be correct but they don't work for my particular example. Only your answer works for me. – nickornotto May 04 '20 at 15:40
0

Perhaps you can try this

let obj = {
  1: {id: 1, first: 1, last: 5},
  2: {id: 2, first: 6, last: 10},
  3: {id: 3, first: 11, last: 15}
}

const newItems = {}
let totalKeys = Object.keys(obj).length

for (let key in obj) {
  newItems[totalKeys] = obj[key];

  totalKeys -= 1;
}

console.log(newItems);
havus
  • 1
  • 1
  • I tried similar code but I was getting: `Element implicitly has an 'any' type because expression of type 'number' can't be used to index type '{}'. No index signature with a parameter of type 'number' was found on type '{}'.` I'm getting the same on your line: `newItems[totalKeys] = obj[key];` This is `TypeScript` thing though which I don't know very well. @havus – nickornotto May 01 '20 at 15:23