如何有条件地合并JavaScript中列表中的某些元素?
问题描述:
我正在构建这个构建器模式,我想将列表中的某些元素合并在一起。但我想以更清晰的方式来做到这一点。这是我迄今为止提出的那种方法,但我相信有更好的方法来做到这一点。如何有条件地合并JavaScript中列表中的某些元素?
function FiltersBuilder() {
this.filters = [];
};
FiltersBuilder.prototype.addFilter = function(options) {
var filter = {
'type': 'selector',
'dimension': options.dimension,
'value': options.value
}
this.filters.push(filter);
return this;
}
FiltersBuilder.prototype.addRegexFilter = function(options) {
var filter = {
'type': 'regex',
'dimension': options.dimension,
'pattern': options.value
}
this.filters.push(filter);
return this;
}
FiltersBuilder.prototype.not = function() {
var not = {
'type': 'not'
};
this.filters.push(not);
return this;
}
FiltersBuilder.prototype.getFilters = function() {
var result = [];
this.filters.forEach(function each(filter, index, theFilters) {
if (filter.type === 'not') {
var filterToMerge = theFilters[index + 1];
var mergedFilter = _.merge(filter, {field: filterToMerge});
result.push(mergedFilter);
} else {
if(index > 0) {
notFilter = theFilters[index - 1];
if(notFilter.type === 'not') {
return;
}
}
result.push(filter);
}
});
return result;
}
var filterBuilder = new FiltersBuilder();
filterBuilder.addFilter({
dimension: '_o',
value: 'origin'
});
filterBuilder.not().addRegexFilter({
dimension: 'cTy',
value: 'value'
});
console.log(filterBuilder.getFilters());
如果not
方法添加过滤器之前被调用,我想合并not
过滤器的下一个元素,并且对象添加到列表result
。但是,如果在添加过滤器之前未调用not
,则不要执行任何操作,只需将过滤器添加到result
列表中即可。
答
不是把not
作为过滤器被添加到过滤器列表,并处理的时候你得到的过滤器,把它作为改性剂 - 的标志。在FiltersBuilder
对象上维护一个not
属性,初始化为false
,其中FilterBuilders.not
的调用将切换。在每个筛选器上,还要添加一个not
属性,该属性由标志的当前值设置(然后被重置)FilterBuilders
。换句话说:
function FiltersBuilder() {
this.filters = [];
this.not = false;
};
FiltersBuilder.prototype.addFilter = function(options) {
var filter = {
'type': 'selector',
'dimension': options.dimension,
'value': options.value,
not: this.not
}
this.not = false;
this.filters.push(filter);
return this;
}
FiltersBuilder.prototype.addRegexFilter = function(options) {
var filter = {
'type': 'regex',
'dimension': options.dimension,
'pattern': options.value,
not: this.not
}
this.not = false;
this.filters.push(filter);
return this;
}
FiltersBuilder.prototype.not = function() {
this.not = !this.not;
}
FiltersBuilder.prototype.getFilters = function() {
return this.filters;
}
var filterBuilder = new FiltersBuilder();
filterBuilder.addFilter({
dimension: '_o',
value: 'origin'
});
filterBuilder.not().addRegexFilter({
dimension: 'cTy',
value: 'value'
});
console.log(filterBuilder.getFilters());
如果您希望能够说filterBuilder.not.addFilter
(不not
后的括号),然后定义not
作为一个getter,即
Object.defineProperty(FiltersBuilder.prototype, "not", {
get: function() {
this.not = !this.not;
return this;
}
});
答
那么,怎么样,如果我们这样做从右边重复它,并使用unshift
代替push
:
getFilters = function(){
return this.filters.reduceRight(function(results, filter){
if(filter.type === 'not'){
//get filter to 'not'
var notFilter = results[0];
Object.assign(notFilter, filter); //Or _.merge
} else {
results.unshift(filter);
}
return results;
}, []);
}
或者,你可以用push
代替unshift
,抢到的最后一个元素该数组作为否定(而不是第一个)的过滤器并反转结果。
getFilters = function(){
return this.filters.reduceRight(function(results, filter){
if(filter.type === 'not'){
//get filter to 'not'
var notFilter = results[results.length - 1];
Object.assign(notFilter, filter); //Or _.merge
} else {
results.push(filter);
}
return results;
}, []).reverse();
}
我喜欢你的方法比我好。谢谢! – toy