totalnoob
totalnoob

Reputation: 2741

sorting values in an object via its values - js

In order to better understand how to manipulate objects, I'm trying to sort an object based on its values.

eg.

let obj = {
    1: 5,
    2: 4,
    3: 200,
    4: 3,
    5: 1
}

and I want an output of

{
    3: 200,
    1: 5,
    2: 4,
    4: 3,
    5: 1
}

I've looped through the object and added its key value pairs into a new array, which I then sort by the values.

the new array looks like this

[
    [3, 200],
    [1, 5],
    [2, 4],
    [4, 3],
    [5, 1]
]

I then loop through this array and create a new object from it, but it's coming out as

{ 1: 5, 2: 4, 3: 200, 4: 3, 5: 1 }

why?

let obj = {
  1: 5,
  2: 4,
  3: 200,
  4: 3,
  5: 1
}

const sortObj = o => {
  const arr = [];
  const _obj = {};

  for (const v in o) arr.push([v, o[v]]);

  arr.sort((a, b) => b[1] - a[1]);

  for (const v of arr) {
    console.log(v);
    /*
    [
      [3, 200],
      [1, 5],
      [2, 4],
      [4, 3],
      [5, 1]
    ]
    */
    const [key, val] = v;
    console.log(key, val);
    _obj[key] = val;
  }

  return _obj;
}

console.log(sortObj(obj));

Upvotes: 0

Views: 54

Answers (3)

JohanP
JohanP

Reputation: 5472

Use Map if you can, it'll preserve order as mentioned in my comment above. The bonus of using Map, your keys won't get converted to strings, it preserves the type too.

let obj = {
  1: 5,
  2: 4,
  3: 200,
  4: 3,
  5: 1
}

const sortObj = o => {
  const arr = [];
  const map = new Map();

  for (const v in o) arr.push([v, o[v]]);

  arr.sort((a, b) => b[1] - a[1]);

  for (const v of arr) {
    console.log(v);
    /*
    [
      [3, 200],
      [1, 5],
      [2, 4],
      [4, 3],
      [5, 1]
    ]
    */
    const [key, val] = v;
    //console.log(key, val);
    map.set(key,val);
  }

  return map;
}
sortObj(obj).forEach((k,v)=>console.log(v,k))

Upvotes: 0

Tyler Roper
Tyler Roper

Reputation: 21672

As of ES2015, your objects keys will almost always preserve their order of insertion. However, one of the few notable exceptions is when your keys are integers.

The example below shows that the sort works fine when we use string keys instead...

let obj = {
  test: 5,
  this: 4,
  out: 200,
  and: 3,
  see: 1
}

const sortObj = o => {
  const arr = [];
  const _obj = {};

  for (const v in o) arr.push([v, o[v]]);

  arr.sort((a, b) => b[1] - a[1]);

  for (const v of arr) {
    const [key, val] = v;
    _obj[key] = val;
  }

  return _obj;
}

console.log(sortObj(obj));

Alternatively, use a Map instead, which always preserves order.

let obj = {
  1: 5,
  2: 4,
  3: 200,
  4: 3,
  5: 1
}

const sortObj = o => {
  const arr = [];
  const _obj = new Map();

  for (const v in o) arr.push([v, o[v]]);

  arr.sort((a, b) => b[1] - a[1]);

  for (const v of arr) {
    const [key, val] = v;
    _obj.set(key, val);
  }

  return _obj;
}

var sortedMap = sortObj(obj);
sortedMap.forEach((val, key) => console.log(`${key}: ${val}`));

Upvotes: 1

Rainer Plumer
Rainer Plumer

Reputation: 3753

Well, there is already a valid answer above but ill post it since i already started to play around with the ordering and have a bit shorter version.

Related reading: Does JavaScript Guarantee Object Property Order?

let obj = {
    1: 5,
    2: 4,
    3: 200,
    4: 3,
    5: 1
}
sortedObj = Object.keys(obj).sort((key1, key2) => {
    if (obj[key1] > obj[key2]) {return -1;}
    if (obj[key1] < obj[key2]) {return 1;}
    return 0;
}).reduce((acc, key) => {
    acc['i_'+key] = obj[key];
    return acc;
}, {});

Upvotes: 1

Related Questions