1

I have a JS object defined as this {0: 3, 2: 2, 4: 1}, and I want to sort only the values, and leave the keys in tact. What I mean is that after the object is sorted, the end result should be {0: 1, 2: 2, 4: 3}, so only the values change their places and not the keys.

I have the following code segment:

let list = {0: 3, 2: 2, 4: 1};
Object.keys(list)
      .sort((a, b) => list[a]-list[b])
      .reduce((obj, key) => ({
          ...obj, 
          [key]: list[key]
      }), {});

But, it doesn't seem to work. In fact, it doesn't seem to sort it at all. Any ideas how to achieve what I want in JS?

tinker
  • 2,884
  • 8
  • 23
  • 35

3 Answers3

2

You could sort the values, the keys stays in ascending order, because object's keys who are integers are sorted by default. Later assign the sorted values to the keys.

var list = { 0: 3, 2: 2, 4: 1 },
    values = Object.values(list).sort((a, b) => a - b),
    result = Object.assign(...Object.keys(list).map((k, i) => ({ [k]: values[i] })));

console.log(result);
Nina Scholz
  • 376,160
  • 25
  • 347
  • 392
  • This is very nice. I'd written my own solution (using Ramda) and was going to see how easily it ported to plain JS, when I saw this much better one. well done! – Scott Sauyet Feb 13 '18 at 20:06
0

There are more elegant solutions involving 3rd party libraries (need zip, partition, etc.), but this should get you there:

let foo = {0: 3, 2: 2, 4: 1};

// here we'll just sort the keys and values independently and then
// recombine them
let keys = Object.keys(foo).sort((a, b) => a - b);
let vals = Object.values(foo).sort((a, b) => a - b);
let result = keys.reduce((acc, k, i) => (acc[k] = vals[i], acc), {});
Jared Smith
  • 19,721
  • 5
  • 45
  • 83
0

Another solution more

let list = {
   0: 3,
   2: 2,
   4: 1
}

let values=Object.values(list).sort()

Object.keys(list)
  .sort()
  .reduce((obj, key, i) => ({
      ...obj,
        [key]: values[i]
  }), {});
FPast
  • 69
  • 2