Kotlin 如何基于动态创建的谓词集合筛选对象列表

Kotlin 如何基于动态创建的谓词集合筛选对象列表,kotlin,filter,Kotlin,Filter,我正在开发一个搜索/过滤功能,在这个功能中,用户应该能够过滤事件列表,以适应他将在运行时生成的模式 我做了一个函数过滤器,它循环遍历用户设置的所有约束,然后过滤结果 我的问题是我复制了很多次列表,我想知道是否有一种方法可以让我以更具声明性(kotlin-)的方式进行这种复杂的过滤,而不会产生副作用 fun过滤器(查询:过滤器,事件列表):列表{ var events=eventsIn query.filters.forEach{filter-> if(filter.key为EventFilter

我正在开发一个搜索/过滤功能,在这个功能中,用户应该能够过滤事件列表,以适应他将在运行时生成的模式

我做了一个函数过滤器,它循环遍历用户设置的所有约束,然后过滤结果

我的问题是我复制了很多次列表,我想知道是否有一种方法可以让我以更具声明性(kotlin-)的方式进行这种复杂的过滤,而不会产生副作用

fun过滤器(查询:过滤器,事件列表):列表{
var events=eventsIn
query.filters.forEach{filter->
if(filter.key为EventFiltersListStuff){
events=when(filter.key作为EventFiltersListStuff){
PLACE->events.filter{event->(filter.value作为列表)。包含(event.location.PLACE)}
AREA->events.filter{event->(filter.value作为列表)。包含(event.location.AREA)}
CATEGORY->events.filter{event->(filter.value作为列表)。任何{it in event.CATEGORY}
流派->events.filter{event->(filter.value作为列表)。包含(event.GENRE)}
}
}否则{
events=when(filter.key作为EventFilters){
TITLE->events.filter{event->event.TITLE.contains(filter.value为字符串,true)}
PRICELT->events.filter{event->event.price events.filter{event->event.price>=filter.value as Int}
TIMELT->events.filter{event->event.time events.filter{event->event.time>=filter.value as Int}
}
}
}
返回事件
}
模型看起来像这样

数据类事件(
val标题:字符串,
瓦尔流派:弦乐,
val image:String,
val-link:String,
val类别:列表,
val价格:整数,
val text:String,
val票:字符串,
时间:长,
val位置:位置
)
我有两个枚举,一个用于包容性过滤,用户可以根据焦点属性的多个实例过滤列表

另一个是非包容性的,只会删除与查询不匹配的所有实体

枚举类EventFiltersListStuff(val str:String,):FilterType{ 地点(“地点”), 区域(“区域”), 类别(“类别”), 流派(“流派”); 重写fun str():String=str } 枚举类事件筛选器(val str:String,):筛选器类型{ PRICELT(“PRICELT”), PRICEGT(“PRICEGT”), 时间线(“时间线”), TIMEGT(“timestampGT”), 所有权(“所有权”); 重写fun str():String=str } 下一个代码块不太相关,但我将包含它是为了透明,因为它用于函数中,这是我问题的核心

接口过滤器类型{
fun str():字符串
}
类筛选器专用构造函数(val筛选器:映射){
类生成器{
私有变量过滤器:MutableMap=mutableMapOf()
趣味过滤器(键:FilterType,值:Any)=应用{
this.filters[key]=何时(this.filters[key]){
is List->(this.filters[key]as List)+listOf(value)
可比较->列表(this.filters[key],value)
其他->价值
}
}
fun build():过滤器{
返回过滤器(过滤器)
}
}
}

我还使用
过滤器
在GraphQL查询中生成一个过滤器,这就是我在枚举中使用字符串的原因。

简单而有效的解决方案就是将所有过滤器结合起来过滤每个事件

typealias SingleFilter=Map.Entry//您可能希望将其重新建模为一个密封类,稍后将详细介绍
有趣的SingleFilter.isMatching(事件:事件):布尔=。。。
fun List.applyFilters(filters:List)=filter{event->filters.all{it.isMatching(event)}


通过将筛选器重新构建为密封类,用多态性替换实例检查和枚举,可以极大地改进模型。这将带来类型安全的巨大好处。您可以为两个筛选案例创建包含两个组的层次结构。您可以定义筛选器名称和类别之间的映射e、 将序列化与过滤器逻辑分离。

简单而有效的解决方案就是将所有过滤器结合起来过滤每个事件

typealias SingleFilter=Map.Entry//您可能希望将其重新建模为一个密封类,稍后将详细介绍
有趣的SingleFilter.isMatching(事件:事件):布尔=。。。
fun List.applyFilters(filters:List)=filter{event->filters.all{it.isMatching(event)}


通过将筛选器重新构建为密封类,用多态性替换实例检查和枚举,可以极大地改进模型。这将带来类型安全的巨大好处。您可以为两个筛选案例创建包含两个组的层次结构。您可以定义筛选器名称和类别之间的映射e、 将序列化与过滤器逻辑分离。

谢谢,这看起来很棒,我将尝试使用密封类和多态性。谢谢,谢谢,这看起来很棒,我将尝试使用密封类和多态性。谢谢