8

我正在将一个数组传递给新集合。是否可以通过传递第二个参数来过滤数组并检查数组中对象的属性并仅在它通过过滤器测试时才创建集合。

collection = new Backbone.Collection([{name:'xy',age:24},{name:'y',age:35}])

我可以只为不到 30 年的对象创建一个集合吗?

4

2 回答 2

5

在传入集合之前,您可以在数组上使用_.filter

collection = new Backbone.Collection(
     _.filter([{name:'xy',age:24},{name:'y',age:35}], 
              function(item) { return item.age < 30; }));

或者您可以将自定义过滤逻辑移动到您的集合initialize中,您将在其中获得models可以修改/过滤的数组

var Under30 = Backbone.Collection.extend({
    initialize: function(models, options) {
        for(var i = models.length - 1; i > 0; i-- ){
            if (models[i].age > 30){
                models.splice(i,1);
            }
        }
    }
});

var collection = new Under30([{name:'xy',age:24}, {name:'y',age:35}]);
console.log(collection.models.length); // will be 1

演示JSFiddle

您可以通过在 options 参数中提供过滤谓词来扩展它

var FilteredCollection = Backbone.Collection.extend({
        initialize: function(models, options) {
            for(var i = models.length - 1; i > 0; i-- ){
                if (options.filter && options.filter(models[i])){
                    models.splice(i,1);
                }
            }
        }
    });

并与它一起使用

var collection = new FilteredCollection(
      [{name:'xy',age:24}, {name:'y',age:35}], 
      {
          filter: function(item) { 
              return item.age > 30; 
          }
      }
);
console.log(collection.models.length); // will be 1
于 2013-08-30T12:18:34.183 回答
1

更新

您对创建集合之前的验证感兴趣,就像之前的答案一样 - 我们将创建一个函数,让您可以重用该策略来根据您想要的条件验证任何集合。

//A collection that validates the correctness of the given elements
// based on a predicate (condition). If the items do not _all_ pass
// the condition - the collection will not be created and an error will
// be thrown.
function validatingCollection(predicate){
    return function(arr){
        //first we assert an array is passed if it's possible to assert
        if(Array.isArray && !Array.isArray(arr)){
            throw new Error("Can only pass array to filteredCollection");
        }
        //for older browsers - use _.every 
        // now we validate they all pass the condition
        if(!arr.every(predicate){
            throw new Error("Validation error, not all elements pass");
        }
        //they all pass, create the collection
        return new Backbone.Collection(arr);
    };
};

现在,我们可以创建这样一个集合,它验证每个元素的年龄至少为 30:

var ageValidated = validatedCollection(function(obj){ return obj.age < 30; });
//create a new age validatedcollection
try{
    var collection = new ageValidated([{name:'xy',age:24},{name:'y',age:35}]); 
}catch(e){
    // the above throws an error because of the object with age 24
}
//however - this works, and creates a new collection
var collection = new ageValidated([{name:'xy',age:32},{name:'y',age:35}]); 

如果您只是想过滤您不喜欢的元素 - 如果不是所有元素都通过验证而不是抛出错误,您可以执行以下操作:

collection = new Backbone.Collection([{name:'xy',age:24},
                                      {name:'y',age:35}].filter(function(obj){
                                          return obj.age < 30;
                                      });

或者,您可以创建自己的过滤集合构造函数以供重用

function filteredCollection(predicate){
    return function(arr){
        //first we assert an array is passed if it's possible to assert
        if(Array.isArray && !Array.isArray(arr)){
            throw new Error("Can only pass array to filteredCollection");
        }
        return new Backbone.Collection(arr.filter(predicate));
    };
};

这让我们可以:

var ageFilter = filteredCollection(function(obj){ return obj.age < 30; });
    //create a new age collection
var collection = new ageFilter([{name:'xy',age:24},{name:'y',age:35}]); 

另一个答案建议_.filter使用原生 Array.filter ,如果您必须支持旧浏览器,这可能会有所帮助。

于 2013-08-30T12:20:13.020 回答