1

我有一个集合,我试图将每个模型的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]

4

2 回答 2

2

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

filtered = this.filter(function(doc) {
  return docIds.indexOf(doc.get('docId')) != -1;
});
于 2013-08-08T19:23:04.213 回答
1

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

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

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

于 2013-08-08T19:38:12.993 回答