Imagine a Model/Collection like:
var AModel = Backbone.Model.extend({
defaults: {
a: 'a string',
b: 'another string',
c: 'yet another string'
}
});
var ACollection = Backbone.Collection.extend({
model: AModel,
comparator: function(amodel) {
...
}
});
How could I write a comparator to implement a multi-level sort? I'd like to sort by AModel
's a
attribute, then by its b
attribute, and then by its c
attribute.
I've hacked together a comparator that looks something like this, but I want to know if there is a better/smarter way?
comparator: function(amodel) {
var s = '',
assumed_max_length_of_any_attribute = 30;
s += amodel.get('a');
while (s.length < assumed_max_length_of_any_attribute) {
s += ' ';
}
s += amodel.get('b');
while (s.length < assumed_max_length_of_any_attribute) {
s += ' ';
}
s += amodel.get('c');
while (s.length < assumed_max_length_of_any_attribute) {
s += ' ';
}
return s;
}
Then, s
becomes properly padded with spaces and should be in "lexical" order with multiple levels. But it all feels very gross compared to the beauty of python's stable multi-level sort (if somehow the above had analogous equivalents in python):
collection.sort(key=lambda x: x.get('c'))
collection.sort(key=lambda x: x.get('b'))
collection.sort(key=lambda x: x.get('a'))
Is there a better way?
The backbone documentation says:
Comparator function can be defined as either a sortBy (pass a function that takes a single argument), or as a sort (pass a comparator function that expects two arguments).
http://documentcloud.github.com/backbone/#Collection-comparator
You could use the second way and implement your comparison based on two elements given.
Maybe something like this:
helper: function (c1, c2) {
if (c1 < c2) return -1;
if (c1 > c2) return +1;
return 0;
}
comparator: function (model1, model2) {
return _.reduce(["c", "b", "a"], function (acc, comp) {
return acc !== 0 ? acc : this.helper(model1[comp], model2[comp])
}, 0);
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With