user12188450
user12188450

Reputation:

getting values and keys in separate arrays sorted by values

Suppose I have an object {'a':20,'b':6,'c':21,'d':12}

After getting sort by values in descending order, The desired output : Keys: ['c','a','d','b'] and Values: [21,20,12,6]

How can I achieve that efficiently? I came to knew that we cannot we cant sort js object keys based on values, since the order of keys is random everytime.

Upvotes: 0

Views: 57

Answers (4)

Srinivas
Srinivas

Reputation: 364

1) Get keys from an object

2) Sort keys based on val comparision

function cmp(a, b) {
  return (a < b) ? 1 : (a > b) ? -1 : 0
}

function sortObj(obj) {
   const keys = Object.keys(obj).sort((x,y) => cmp(obj[x],obj[y]))
   const vals = keys.map(x => obj[x])
   return {sortedKeys: keys, sortedValues: vals}
}

result = sortObj({'a':20,'b':6,'c':21,'d':12})
console.log(result)

Answer

{
sortedKeys:  ["c", "a", "d", "b"]
sortedValues: [21, 20, 12, 6]
}

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074465

I came to knew that we cannot we cant sort js object keys based on values, since the order of keys is random everytime.

That's not true (it's not random, and it's not different every time), but sorting JavaScript objects is almost never useful.

You have several options to get the array you've shown. One simple one is to use Object.entries to get an array of [key, value] arrays, then sort that, then get just the keys from it via map:

const obj = {'a':20,'b':6,'c':21,'d':12};
const keys = Object.entries(obj)
    .sort(([k1, v1], [k2, v2]) => v2 - v1)
    .map(([k, v]) => k);
console.log(keys);

Object.entries is relatively new, but easily polyfilled if needed.

If you need it in ES5 (with Object.entries polyfilled):

var obj = {'a':20,'b':6,'c':21,'d':12};
var keys = Object.entries(obj)
    .sort(function(e1, e2) {
        return e2[1] - e1[1];
    })
    .map(function(e) {
        return e[0];
    });
console.log(keys);


In a comment you've asked how to have the values in a separate array as well. You can either build that value array as a side-effect of map by pushing into it, like this:

const obj = {'a':20,'b':6,'c':21,'d':12};
const values = [];
const keys = Object.entries(obj)
    .sort(([k1, v1], [k2, v2]) => v2 - v1)
    .map(([k, v]) => {
        values.push(v);
        return k;
    });
console.log(keys);
console.log(values);

...or if using map for side-effects bothers you (it's often not best practice), just use forEach (or for-of) instead:

const obj = {'a':20,'b':6,'c':21,'d':12};
const keys = [];
const values = [];
Object.entries(obj)
    .sort(([k1, v1], [k2, v2]) => v2 - v1)
    .forEach(([k, v]) => {
        keys.push(k);
        values.push(v);
    });
console.log(keys);
console.log(values);

The for-of version:

const obj = {'a':20,'b':6,'c':21,'d':12};
const keys = [];
const values = [];
for (const [k, v] of Object.entries(obj).sort(([k1, v1], [k2, v2]) => v2 - v1)) {
    keys.push(k);
    values.push(v);
}
console.log(keys);
console.log(values);

(You might use a temporary variable for the result of .sort, then use for (const [k, v] of theTemporaryVariable) {.)

Upvotes: 3

kostik
kostik

Reputation: 1209

const obj = {'a':20,'b':6,'c':21,'d':12};

const result = Object.keys(obj)
  .reduce((acc, key) => {
    const value = obj[key];
    acc.push({ key, value });
    acc.sort((a, b) => b.value - a.value);
    return acc;
  }, []);

console.log(result);

output

[
  { key: 'c', value: 21 },
  { key: 'a', value: 20 }
  { key: 'd', value: 12 }
  { key: 'b', value: 6 }
]

Upvotes: 1

Yahiya
Yahiya

Reputation: 791

Try this.

const list = {'a':20,'b':6,'c':21,'d':12};

let myObject = Object.fromEntries(Object.entries(list).sort( (a,b) => b[1] - a[1] ));

Object.prototype.mySplit = function() {
  return Object.keys(this).map((key) => {
    return {
      key: key,
      value: this[key]
    };
  });
}

let keys = [];
let values = [];

let properties = myObject.mySplit();
for (var i = 0; i < properties.length; i++) {
    keys.push(properties[i]['key']);
    values.push(properties[i]['value']);
}

console.log(keys);
console.log(values);

Upvotes: 0

Related Questions