5

I have an object that looks like this:

var unsorted = {a: 15, b: 1,c: 2, d: 4, e: 3, f: 6, g: 1}

And I am interested in sorted it in descending order with lodash, so the expected result should be:

var sortd = {b: 1, g: 1,c: 2, e: 3, d: 4, f: 6, a: 15}

I have tried using lodash orderBy but it gives an array of just the values sorted.

_.orderBy(tempCount, Number, ['desc'])

//Result
[1,1,2,3,4,6,15]
Dave Kalu
  • 1,133
  • 2
  • 13
  • 29
  • 2
    Objects don't have order. you need to use array if order is important – Code Maniac Feb 04 '19 at 17:00
  • The answer is no! Even if you build an object with sorted properties, it is not guaranteed that they will display in the same order in the future. – Melchia Feb 04 '19 at 17:11
  • 1
    come on! the order is now standard. first comes index same items in order and the the rest in insertation order. – Nina Scholz Feb 04 '19 at 17:29

3 Answers3

8

JavaScript does not guarantee the order of keys in an object, this is why lodash returns you an array, because an object with ordered keys is not guaranteed. See this SO question.

However you can use a Map, which does guarantee the order of the keys.

You can do this with pure JavaScript:

const unsorted = { a: 15, b: 1,c: 2, d: 4, e: 3, f: 6, g: 1 };

const sorted = new Map(Object.entries(unsorted).sort((a, b) => a[1] - b[1]));

for (const [key, val] of sorted) {
  console.log(key, val);
}

You have multiple ways to iterate over the content of the resulting map:

  • map.values(): get the array of values
  • map.entries(): get an array of [key, value] pairs
  • map.keys(): get an array of keys

See the doc about Map.

jo_va
  • 11,779
  • 3
  • 20
  • 39
  • Thanks @jo_va, but I figured out that a simple `Object.entries(unsorted).sort((a, b) => a[1] - b[1])` does the same thing without the need for the for-of loop. – Dave Kalu Feb 04 '19 at 17:57
  • Exactly, if you want the array, as shown in my answer, I just wrap this result in a Map if you want to access your values by keys, as you would with an object – jo_va Feb 04 '19 at 17:59
  • Oh yeah. I understand. Thank you regardless. – Dave Kalu Feb 04 '19 at 18:06
7

You could build a new object with the sorted key/value pairs.

The actual standard or the order of properties:

  • sort index like keys first, in order
  • keep all other keys in insertation order

For a complete control over the order, take an array with the keys an take it as sorted accessor for the values.

var unsorted = { a: 15, b: 1,c: 2, d: 4, e: 3, f: 6, g: 1 },
    sorted = _(unsorted)
        .toPairs()
        .orderBy([1], ['desc'])
        .fromPairs()
        .value()
        
console.log(sorted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>

Descending sort with _.orderBy by using a the last parameter for a specific order, instead of _.sortBy, which only allows to sort ascending.

var unsorted = { a: 15, b: 1,c: 2, d: 4, e: 3, f: 6, g: 1 },
    sorted = _(unsorted)
        .toPairs()
        .orderBy(1, 'desc')
        .fromPairs()
        .value()
        
console.log(sorted);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>
Nina Scholz
  • 323,592
  • 20
  • 270
  • 324
1

Here you have another approach (without lodash). Basically we create and array of type [[key1, value1], [key2, value2],...] using the Object.entries(unsorted), then sort that array (ascending/descending) comparing the values, to finally construct again the object structure you have originally, first mapping pairs [key, value] to objects {key: value} and then assigning all these objects to a new one using Object.assign().

var unsorted = {a: 15, b: 1,c: 2, d: 4, e: 3, f: 6, g: 1};

let sortedAsc = Object.entries(unsorted)
    .sort(([k1,v1], [k2,v2]) => v1 - v2)
    .map(([x,y]) => ({[x]:y}));
    
let sortedDesc = Object.entries(unsorted)
    .sort(([k1,v1], [k2,v2]) => v2 - v1)
    .map(([x,y]) => ({[x]:y}));

let objSortedAsc = Object.assign({}, ...sortedAsc);
let objSortedDesc = Object.assign({}, ...sortedDesc);

console.log("ASC: ", objSortedAsc, "DESC: ", objSortedDesc);
.as-console {background-color:black !important; color:lime;}
.as-console-wrapper {max-height:100% !important; top:0;}
Shidersz
  • 15,614
  • 2
  • 15
  • 40