Tell me more ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

Say I have an array of Employee Objects:

var Employee = function(fname, age) {
    this.fname = fname;
    this.age = age;
}

var employees = [
    new Employee("Jack", "32"),
    new Employee("Dave", "31"),
    new Employee("Rick", "35"),
    new Employee("Anna", "33")
];


At this point, employees.sort() means nothing, because the interpreter does not know how to sort these custom objects. So I pass in my custom sort function.

employees.sort(function(employee1, employee2){
    return employee1.age > employee2.age;
});


Now employees.sort() works dandy.

But what if I also wanted to control what field to be sorted on, passing it in somehow during runtime? Can I do something like this?

employees.sort(function(employee1, employee2, on){
    if(on === 'age') {
        return employee1.age > employee2.age;
    }
    return employee1.fname > employee2.fname;
});

I can't get it to work, so suggestions? Design pattern based refactoring perhaps?

share|improve this question

3 Answers

up vote 8 down vote accepted
function getSortFunction(fieldName) {
    return function(employee1, employee2) {
        return employee1[fieldName] > employee2[fieldName];
    }
}

employees.sort(getSortFunction("myField"));

Another solution is to use Function.prototype.bind if you are not afraid of it :)

function mySorter(fieldName, employee1, employee2) {
    return employee1[fieldName] > employee2[fieldName];
}

employees.sort(mySorter.bind(null, "myField"));
share|improve this answer

You could use the excellent library underscore.js' sortBy method.

For example:

var arr = [
    { name:"a", age:100 },  
    { name:"b", age:90 },
    { name:"c", age:80 },
    { name:"d", age:70 }
];

var sorted = _.sortBy(arr, "age");
console.log( sorted );

or in your case:

_.sortBy(employees, "age");
share|improve this answer

I provide my own sortBy method for arrays that lets you specify an arbitrary number of fields to sort by, using a Schwartzian transform:

Example 1

var a=[ {c:"GK",age:37}, {c:"ZK",age:13}, {c:"TK",age:14}, {c:"AK",age:13} ];

a.sortBy( function(){ return this.age } );                                   
// [ {c:"ZK",age:13}, {c:"AK",age:13}, {c:"TK",age:14}, {c:"GK",age:37} ] 

a.sortBy( function(){ return [this.age,this.c] } );                          
// [ {c:"AK",age:13}, {c:"ZK",age:13}, {c:"TK",age:14}, {c:"GK",age:37} ] 

a.sortBy( function(){ return -this.age } );                                  
// [ {c:"GK",age:37}, {c:"TK",age:14}, {c:"ZK",age:13}, {c:"AK",age:13} ] 

Example 2:

var n=[ 1, 99, 15, "2", "100", 3, 34, "foo", "bar" ];                        

n.sort();                                                                    
// [ 1, "100", 15, "2", 3, 34, 99, "bar", "foo" ]                         

n.sortBy( function(){ return this*1 } );                                     
// [ "foo", "bar", 1, "2", 3, 15, 34, 99, "100" ]                         

n.sortBy( function(o){ return [typeof o,this] } );                           
// [1, 3, 15, 34, 99, "100", "2", "bar", "foo"]                           

n.sortBy(function(o){ return [typeof o, typeof o=="string" ? o.length : o] })
// [1, 3, 15, 34, 99, "2", "100", "bar", "foo"]                           

The Code

(function(){
  // This code is copyright 2012 by Gavin Kistner, [email protected]
  // License: http://phrogz.net/JS/_ReuseLicense.txt
  if (typeof Object.defineProperty === 'function'){
    try{Object.defineProperty(Array.prototype,'sortBy',{value:sb}); }catch(e){}
  }
  if (!Array.prototype.sortBy) Array.prototype.sortBy = sb;

  function sb(f){
    for (var i=this.length;i;){
      var o = this[--i];
      this[i] = [].concat(f.call(o,o,i),o);
    }
    this.sort(function(a,b){
      for (var i=0,len=a.length;i<len;++i){
        if (a[i]!=b[i]) return a[i]<b[i]?-1:1;
      }
      return 0;
    });
    for (var i=this.length;i;){
      this[--i]=this[i][this[i].length-1];
    }
    return this;
  }
})();
share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.