在嵌套对象中搜索文本(Backbone.js集合作为示例)
我有一个backbone.js集合,我需要在其上进行全文搜索。 我手头的工具如下:
Backbone.js,underscore.js,jQuery
对于那些不熟悉骨干的人:
骨干集合只是一个对象。 在集合内部有一个带模型的数组。 每个模型都有一个包含属性的数组。 我必须在每个属性中搜索字符串。
我用的代码是:
query = 'some user input'; query = $.trim(query); query = query.replace(/ /gi, '|'); var pattern = new RegExp(query, "i"); // this.collection.forEach is the same as _.each // only it get's the models from the collection this.collection.forEach(function(model) { var check = true; _.each(model.attributes, function(attr){ if(pattern.test(attr) && check){ // Do something with the matched item check = false; } }, this); }, this);
也许我正在使用的工具之一有更好的方法来解决这个问题?
Backbone将许多下划线方法扩展到Collection
类中,因此您可以摆脱其中的一些内容。 真的,你可能想在集合本身作为一种方法来实现这个,然后我可能会使用一个很好的老式for
循环看看那些键,特别是如果我想要突破它。
// in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); var collection = this; collection.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ callback.call( collection, model, k ); break; // ends the for loop. } } }); } // later collection.search('foo', function( model, attr ){ console.log('found foo in '+model.cid+' attribute '+attr); });
也就是说,这只会从集合中返回第一场比赛。 您可能更喜欢将结果数组作为[model,attribute]对返回的实现。
// in Backbone.Collection.extend search: function( query, callback ){ var matches = []; var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); this.each(function(model) { for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(model.attributes[k]) ){ matches.push([model, k]); } } }); callback.call( this, matches ); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' attribute '+match[1]); }); });
或者,如果您想要匹配但不关心匹配哪个属性的模型数组,则可以使用filter
// in Backbone.Collection.extend search: function( query, callback ){ var pattern = new RegExp( $.trim( query ).replace( / /gi, '|' ), "i"); callback.call( this, this.filter(function( model ){ for( k in model.attributes ){ if( model.attributes.hasOwnProperty(k) && pattern.test(k) ) return true; } })); } // later collection.search('foo', function( matches ){ _.each(matches, function(match){ console.log('found foo in '+match[0].cid+' somewhere'); }); });
你的内心each
都在短路,所以你可以切换到_.any()
而不是你的_.each()
和一个标志组合; 一旦回调函数返回true
, any
停止迭代,并且如果可用,也委托给本机some
方法。
this.collection.each(function(model) { _(model.attributes).any(function(attr, key) { if(!pattern.test(attr)) return false; // Do something with the matched item... return true; }); });
我也删除了this
参数的上下文,因为你没有在任何地方使用this
,如果“做某事”需要它们你可以把它们放回去。
如果简单的正则表达式搜索不够好,您可以查看集合的词干和反向索引。