5

I have an array of objects with two properties: Name and Hours.

For example:

array = [
    {name: "ANDY", hours: 40 }, 
    {name: "ANDY", hours: 50 }, 
    {name: "GREG", hours: 40 },
]

For example in my array I would like the result of the sorting to have the Andy with the most hours first, then Andy with slightly less hours, and then Greg because his name comes later alphabetically and so on and so on.

Since the array.sort() function passes two elements of the array to compare i realise this is not the way to go for me but fail to come up with an elegant solution. Please help me out.

georg
  • 211,518
  • 52
  • 313
  • 390
Rafał Saltarski
  • 707
  • 1
  • 8
  • 20
  • 1
    possible duplicate of [How to sort an array of objects with multiple field values in JavaScript](http://stackoverflow.com/questions/11379361/how-to-sort-an-array-of-objects-with-multiple-field-values-in-javascript) – Felix Kling Apr 23 '13 at 08:26
  • @FelixKling: yes, asked 1000 times already, unfortunately most answers so far are lame. – georg Apr 23 '13 at 08:28

4 Answers4

14

array = [
    {name: "ANDY", hours: 40 }, 
    {name: "GREG", hours: 40 },
    {name: "ANDY", hours: 50 }, 
]

function cmp(x, y) {
  return x > y ? 1 : (x < y ? -1 : 0);
}


array.sort(function(a, b) {
  return cmp(a.name, b.name) || cmp(b.hours, a.hours)
})

console.log(array)

If javascript had a spaceship operator that would be even more elegant. Note that this code is easy to extend to use more properties:

ary.sort(function(a, b) {
    return cmp(a.name, b.name) || cmp(a.age, b.age) || cmp(b.hours, a.hours) || ....
})
georg
  • 211,518
  • 52
  • 313
  • 390
3
var arr = [{
    name: "GREG",
    hours: "40"
}, {
    name: "ANDY",
    hours: "50"
}, {
    name: "ANDY",
    hours: "40"
}];

Array.prototype.sortOn = function(conds){
    this.sort(function(a, b){
        for(var i=0; i < conds.length; i++){
            var c = conds[i].split(" ");
            if(a[c[0]] < b[c[0]]){
                return c[1] == "asc" ? -1:1;
            }
            if(a[c[0]] > b[c[0]]){
                return c[1] == "asc" ? 1:-1;
            }
        }
        return 0;
    });
    return this;
}

arr.sortOn(["name asc", "hours dsc"]);
Diode
  • 24,570
  • 8
  • 40
  • 51
2

You can sort by Name, then sort elements who have the same name by Hours

Example:

var array = [{"Name":"ANDY", "Hours":40},
             {"Name":"ANDY", "Hours":50},
             {"Name":"GREG", "Hours":40}];


var sortedArray = array.sort(function(a,b) {
            return (a["Name"] > b["Name"]) ? 1 : -1;
    }).sort(function(a,b) {
            if(a["Name"] == b["Name"])
                return (a["Hours"] < b["Hours"]) ? 1 : -1;
            else 
                return 0;
    });
Cattode
  • 856
  • 5
  • 11
  • Javascript sort is not guaranteed to be stable, results may vary across implementations. – georg Apr 23 '13 at 08:24
  • Why are you doing property access via brackets as opposed to dot notation? – Evan Trimboli Apr 23 '13 at 08:38
  • Yeah, both notations work for this particular question. Don't know exactly why I preferred using brackets. I guess it's because it is more generic, if someone have a similar question with properties which contains space characters for example. – Cattode Apr 23 '13 at 08:58
2
obj.sort(function(item1,item2) {
  if ( item1.Name < item2.Name )
    return -1;
  if ( item1.Name > item2.Name )
    return 1;
  return item1.Hours - item2.Hours;
});
UltraInstinct
  • 43,308
  • 12
  • 81
  • 104