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