我有一个集合self.models
。我还有一个对象数组,其中包含我希望应用于名为filterArr
的集合的字段和过滤器。这方面的一个例子是:
[{field: "Account", filter: "123"}, {field: "Owner", filter: "Bob"}]
问题是,我不确定如何迭代我的每个模型以仅返回此filterArr
适用的模型,我知道它必须是这样的,但是这是硬编码的:
self.models = _.filter(self.models, function (model) {
model = model.toJSON();
return model.Account === "123" && model.Owner === "Bob";
});
答案 0 :(得分:7)
首先,下划线的过滤器返回Array
,所以你在这里有效地做的是用过滤后的数组替换你的集合。这样的事情会更合适:
this.filtered = _.filter(this.models, ...);
Backbone Collection实现了大部分underscore's useful functions。所以上面的解决方案远非最佳(实际上它并不是按照你想要的方式工作),而是做这样的事情:
this.filtered = this.models.filter(function() {...});
按名称获取和设置模型字段的最佳方法是Backbone get
的{{1}}和set
functions,为什么不使用它们呢? Model
有效,但您只是不必要地复制Model.toJSON()
- 哈希。
attributes
希望这有帮助!
答案 1 :(得分:-2)
基本上你需要迭代模型的属性并将它们的键和值进行比较以过滤属性。
self.models = _.filter(self.models, function (model) {
var fits = true; // does this model "fit" the filter?
model = model.toJSON();
_.each(model, function(modelVal, modelKey) {
_.each(filterArr, function(filter) {
if (modelKey === filter.field && modelVal !== filter.filter) {
fits = false
}
}
})
return fits
})
然而,有了一点下划线魔法,这是一种更棘手的方式。我不确定它在性能方面是否更好,但它确实看起来更好。
// change a bit the way filter is described:
var filter = {Account: '123', Owner: 'Bob'},
// save an array of filter keys (Account, Owner)
filterKeys = _.keys(filter),
// and an array of its values (123, Bob)
filterVals = _.values(filter)
self.models = _.filter(self.models, function (model) {
// pick a subset of model which has the same keys as filter
var filteredSubset = _.pick(model.attributes, filterKeys),
// pick values of this subset
subsetValues = _.values(filteredSubset)
// this values have to be equal to filter's values
// (use .join() to turn array to string before comparison due to references)
return filteredVals.join() === subsetValues.join()
})
请注意,在后一种情况下,所有模型都必须在过滤器中声明所有键。
如果我是你,我正在寻找一种最强大的方法,我会重写第一个例子,但会将_.each
更改为标准for
循环,并尽快返回false
因为满足了第一个“不适合”的价值。