使用复杂的 AND+OR 逻辑过滤 ArrayList
Filter ArrayList using complex AND+OR logic
我希望将自定义模型对象的 ArrayList 过滤为匹配用户 selected 的值。
用户可以以任何方式过滤模型对象的不同字段...
如果它们 select 同一字段的多个值(例如,为 "category" 字段选择早餐和晚餐)匹配任何 selection 的对象应该被返回。如果他们同时使用 "protein" 字段进行过滤并选择 "chicken",则只应返回鸡肉早餐和晚餐。
我目前正在使用 Guava 和 Collections2.filter(...),但似乎无法正确组合 AND/OR 逻辑。
任何指导将不胜感激! :)
编辑:添加代码片段以表明我不是在寻找 "moral support"
Collection<FieldAcceptanceLogItem> objectFilter = allLogItems;
for (final Filter filter : mFilters) {
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
@Override
public boolean apply(@javax.annotation.Nullable FieldAcceptanceLogItem input) {
if (filter.getCategory().equalsIgnoreCase(getString(R.string.sublocation))) {
return input.getSublocation().equalsIgnoreCase(filter.getTitle());
}
else if (filter.getCategory().equalsIgnoreCase(getString(R.string.technology))) {
return input.getTechnology().equalsIgnoreCase(filter.getTitle());
}
else { //(filter.getCategory().equalsIgnoreCase(getString(R.string.component)))
return input.getComponent().equalsIgnoreCase(filter.getTitle());
}
}
});
}
所以看起来你想要子位置、技术和组件的交集。我移动了几件事,应该突出你要解决的问题:
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
@Override
public boolean apply(@javax.annotation.Nullable FieldAcceptanceLogItem input) {
return SublocationFilters.from(mFilters).contains(input.getLocation())
&& TechnologyFilters.from(mFilters).contains(input.getTechnology())
&& ComponentFilters.from(mFilters).contains(input.getComponent());
});
SublocationFilters.from(...)
将为您提供所有子位置过滤器
TechnologyFilters.from(...)
会给你所有的技术过滤器
ComponentFilters.from(...)
将为您提供所有组件过滤器
contains(...)
只是一个方便的方法来做 "filter_1 OR filter_2 OR... filter_n"
不过,如果您确实想遵循该模式,我建议您做更多类似的事情,因为编写测试的次数更少:
new CategoryFilter(mFilters, getString(R.string.component))
.contains(input.getComponent());
我希望将自定义模型对象的 ArrayList 过滤为匹配用户 selected 的值。 用户可以以任何方式过滤模型对象的不同字段...
如果它们 select 同一字段的多个值(例如,为 "category" 字段选择早餐和晚餐)匹配任何 selection 的对象应该被返回。如果他们同时使用 "protein" 字段进行过滤并选择 "chicken",则只应返回鸡肉早餐和晚餐。
我目前正在使用 Guava 和 Collections2.filter(...),但似乎无法正确组合 AND/OR 逻辑。
任何指导将不胜感激! :)
编辑:添加代码片段以表明我不是在寻找 "moral support"
Collection<FieldAcceptanceLogItem> objectFilter = allLogItems;
for (final Filter filter : mFilters) {
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
@Override
public boolean apply(@javax.annotation.Nullable FieldAcceptanceLogItem input) {
if (filter.getCategory().equalsIgnoreCase(getString(R.string.sublocation))) {
return input.getSublocation().equalsIgnoreCase(filter.getTitle());
}
else if (filter.getCategory().equalsIgnoreCase(getString(R.string.technology))) {
return input.getTechnology().equalsIgnoreCase(filter.getTitle());
}
else { //(filter.getCategory().equalsIgnoreCase(getString(R.string.component)))
return input.getComponent().equalsIgnoreCase(filter.getTitle());
}
}
});
}
所以看起来你想要子位置、技术和组件的交集。我移动了几件事,应该突出你要解决的问题:
objectFilter = Collections2.filter(objectFilter, new Predicate<FieldAcceptanceLogItem>() {
@Override
public boolean apply(@javax.annotation.Nullable FieldAcceptanceLogItem input) {
return SublocationFilters.from(mFilters).contains(input.getLocation())
&& TechnologyFilters.from(mFilters).contains(input.getTechnology())
&& ComponentFilters.from(mFilters).contains(input.getComponent());
});
SublocationFilters.from(...)
将为您提供所有子位置过滤器TechnologyFilters.from(...)
会给你所有的技术过滤器ComponentFilters.from(...)
将为您提供所有组件过滤器contains(...)
只是一个方便的方法来做 "filter_1 OR filter_2 OR... filter_n"
不过,如果您确实想遵循该模式,我建议您做更多类似的事情,因为编写测试的次数更少:
new CategoryFilter(mFilters, getString(R.string.component))
.contains(input.getComponent());