Reputation: 1670
I have a collection I am trying to compare each model's docId
attribute to an array of numbers, to return a filtered collection.
If I was comparing the collection's items to a single id, it would be something like:
Docs = Backbone.Collection.extend({
model: Doc,
filter_id: function(docId) {
filtered = this.filter(function(doc) {
return doc.get('docId') === docId;
});
return new Docs(filtered);
}
});
docId = 123;
docs = new Docs;
filteredDocs = docs.filter_id(docId);
How can I amend the above if I'm dealing with docIds = [123, 456, 789]
?
Upvotes: 1
Views: 650
Reputation: 9437
Classic algorithms question. Easy O(n*m) solution based on indexOf() which @McGarnagle mentioned in a different answer. This is perfectly okay if these lists are small:
filtered = this.filter(function(doc) {
return docIds.indexOf(doc.get('docId')) != -1;
});
Slightly more complicated O(n) solution based on a lookup table, which you might need if the lists get big or if this is a hot spot in your code:
var table = {};
docIds.forEach(function(docId){
table[docId] = true;
});
filtered = this.filter(function(doc) {
return table[doc.get('docId')];
});
The reason is that indexOf() has to scan the whole array, repeated for each item in the collection. n=the length of the collection, m=the length of the array, hence O(n*m). Whereas accessing a property on an object is generally going to be O(1) for each item in the collection, hence O(1*n) or just O(n).
Caveat is that the second solution takes up more memory since it creates an extra object and populates it. You have to decide the tradeoff.
Upvotes: 1
Reputation: 102753
Since it's an array of numbers, you could just use indexOf
:
filtered = this.filter(function(doc) {
return docIds.indexOf(doc.get('docId')) != -1;
});
Upvotes: 2