将Backbone集合与数组进行比较

时间:2013-08-08 19:17:13

标签: javascript backbone.js underscore.js

我有一个集合我试图将每个模型的docId属性与一组数字进行比较,以返回过滤后的集合。

如果我将集合的项目与单个id进行比较,则可能是:

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);

如果我正在处理docIds = [123, 456, 789]

,我该如何修改上述内容?

2 个答案:

答案 0 :(得分:2)

由于它是一组数字,您可以使用indexOf

filtered = this.filter(function(doc) {
  return docIds.indexOf(doc.get('docId')) != -1;
});

答案 1 :(得分:1)

经典算法问题。基于indexOf()的简单O(n * m)解决方案,@ McGarnagle在另一个答案中提到了这个解决方案。如果这些列表很小,这是完全可以的:

filtered = this.filter(function(doc) {
  return docIds.indexOf(doc.get('docId')) != -1;
});

基于查找表的O(n)解决方案稍微复杂一点,如果列表变大或者这是代码中的热点,您可能需要这样做:

var table = {};
docIds.forEach(function(docId){
  table[docId] = true;
});
filtered = this.filter(function(doc) {
  return table[doc.get('docId')];
});

原因是indexOf()必须扫描整个数组,对集合中的每个项重复。 n =集合的长度,m =数组的长度,因此为O(n * m)。而对于集合中的每个项目,访问对象上的属性通常将为O(1),因此O(1 * n)或仅O(n)。

警告说,第二个解决方案会占用更多内存,因为它会创建一个额外的对象并填充它。你必须决定权衡。