CrackerKraken
CrackerKraken

Reputation: 59

Sort a collection by multiple fields

How can I sort the models of a collection by two of their attributes?

Here is what I have so far:

 Character = Backbone.Model.extend();

 Characters = Backbone.Collection.extend({
     model: Character,
     comparator: function(character){
         return [character.get('children') != undefined, character.get('age')]
     }
 });

 var myCharacters = new Characters([
     { name: 'Cersei',   age: 32, children: 3 },
     { name: 'Aemon',    age: 100             },
     { name: 'Tyrion',   age: 24              },
     { name: 'Stannis',  age: 33, children: 1 },
     { name: 'Daenerys', age: 14              }
     { name: 'Tywin',    age: 54, children: 3 },
     { name: 'Arya',     age: 9               },
 ]);

 myCharacters.sort;

The models should be sorted by children (do they have children or not), then by age (from oldest to youngest). The resulting order would be : Tywin, Stannis, Cersei, Aemon, Tyrion, Daenerys, Arya

Upvotes: 0

Views: 217

Answers (3)

CrackerKraken
CrackerKraken

Reputation: 59

Ok so I figured it out.

 Characters = Backbone.Collection.extend({
     model: Character,
     comparator: function(c){
         return [c.get('children') ? 0 : 1, 1/c.get('age')];
    }
 });

The sort method orders from smallest value to largest value.
If the character has children, the comparator will return [0, (1/age)]
Else (no children) it will return [1, (1/age)]

The characters will be ordered like this:

 Tywin    [0, 0.019]  
 Stannis  [0, 0.030]  
 Cersei   [0, 0.031]  
 Aemon    [1, 0.010]  
 Tyrion   [1, 0.042]  
 Daenerys [1, 0.071]  
 Arya     [1, 0.111]

Upvotes: 1

Manikandan
Manikandan

Reputation: 3165

Try this out.

comparator: function(char1,char2){

     var child1 = char1.get("children");
    var child2 = char2.get('children');
    var ageDiff = char1.get("age") - char1.get("age");
    if(child1 && child2){
        var diff = child1 - child2;
        if(diff !=0) return diff;
        return  ageDiff;
    }
    if(!child1 && !child2) return ageDiff;
    if(child1) return 1;
    return -1;
}

Upvotes: 0

David Sulc
David Sulc

Reputation: 25994

Your comparator function needs to take to arguments (a, b) and return

  • -1 if a is before b
  • 0 if they're equal
  • 1 if b is before a

See https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort?redirectlocale=en-US&redirectslug=JavaScript%2FReference%2FGlobal_Objects%2FArray%2Fsort

Upvotes: 0

Related Questions