2

I have an object of nested objects and would like to sort by one of the nested values (e.g. "month_sales" descending). This is what the data looks like:

{ 
"Bob": { sales: 13, revenue: 33, month_sales: 149 },
"Bill": { today_sales: 20, week_sales: 38, month_sales: 186 },
"Jane": { today_sales: 17, week_sales: 38, month_sales: 164 }
}

This is what I want it to look like (sort by month_sales descending):

{ 
"Bill": { today_sales: 20, week_sales: 38, month_sales: 186 },
"Jane": { today_sales: 17, week_sales: 38, month_sales: 164 }
"Bob": { sales: 13, revenue: 33, month_sales: 149 },
}

I have looked all over Google and StackOverflow, and have only found a couple answers that deal with sorting an object rather than an array, and in every case the answer has been along the lines of "write a function to convert the object to an array, sort that, and then turn it back into an object."

I'm willing to do that as a last resort, but it seems like I should be able to do this without deconstructing the entire object and putting it back together again. Maybe there's an elegant way to do this in lodash or something?

1

4 Answers 4

1

You can only have sorted arrays, not objects. To do that, you first need to map your object to an array. Here's how you can do it using lodash map() and sortBy():

_(data)
    .map(function(value, key) {
        return _.defaults({ name: key }, value);
    })
    .sortBy('name')
    .value();
// →
// [
//   { name: "Bill", today_sales: 20, week_sales: 38, month_sales: 186 },
//   { name: "Bob", sales: 13, revenue: 33, month_sales: 149 },
//   { name: "Jane", today_sales: 17, week_sales: 38, month_sales: 164 }
// ]

The mapping uses the defaults() function to give each array item a new name property, which is used to sort the array.

Sign up to request clarification or add additional context in comments.

Comments

1

This is not possible because properties of objects do not have a guaranteed order in javascript. You will have to convert it to an array perhaps like this first:

[ 
  { name: "Bob", sales: 13, revenue: 33, month_sales: 149 },
  { name: "Bill", today_sales: 20, week_sales: 38, month_sales: 186 },
  { name: "Jane", today_sales: 17, week_sales: 38, month_sales: 164 }
]

Then when you sort it as an array it will maintain that order.

Comments

0

If you convert your object to an array, then you could sort them by category like this

var arr = [ 
  { name: "Bob", sales: 13, revenue: 33, month_sales: 149 },
  { name: "Bill", today_sales: 20, week_sales: 38, month_sales: 186 },
  { name: "Jane", today_sales: 17, week_sales: 38, month_sales: 164 }
]

arr.sort(function(x, y){
    var category = "month_sales"
    if (x[category] < y[category]) {
        return -1;
    }
    if (x[category] > y[category]) {
        return 1;
    }
    return 0;
});

Comments

0

While you can't sort an object, you can create an index sorted on whatever property you want, e.g. to get a list of the names sorted by month_sales highest to lowest:

var obj = { 
"Bob": { sales: 13, revenue: 33, month_sales: 149 },
"Bill": { today_sales: 20, week_sales: 38, month_sales: 186 },
"Jane": { today_sales: 17, week_sales: 38, month_sales: 164 }
}

var index = Object.keys(obj).sort(function(a,b) {
              return obj[b].month_sales - obj[a].month_sales;
            });

Then get the one with the highest value:

console.log(index[0] + ':' + obj[index[0]].month_sales); // Bill:186

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.