[英]Generic collection filtering using predicates
我在 kotlin 中遇到了一个关于集合过滤的棘手问题......
我有一个管理项目列表的基类,我希望能够使用关键字过滤列表,因此我使用 Filterable 方法扩展了该类。
我想要做的是能够使用这个“基类”扩展多个类,因此所有类的过滤器机制都是相同的。
这些类没有相同的属性...其中,过滤必须根据关键字是否在“名称”中找到,而在另一个类中过滤是在“评论”属性上完成的。
这里有一些代码:
data class ProductInfo(): {
var _name: String
var name: String
get() = _name
set(value) { _name = value }
}
abstract class BaseFirestoreAdapter<T : BaseFirestoreAdapter.DataInterface, VH : RecyclerView.ViewHolder> : RecyclerView.Adapter<VH>(), Filterable
{
var sourceList: MutableList<ProductInfo> = ArrayList()
...
override fun performFiltering(keyword: CharSequence): FilterResults {
val keywordRegex = keyword.toString().toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.LITERAL))
filteredList = sourceList.filter {
keywordRegex.containsMatchIn(Normalizer.normalize(it.name, Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
results.values = filteredList.sortedWith(orderComparator)
results.count = filteredList.size
}
...
}
我开发了“基类”,因此它可以与上面提到的第一个类一起使用(过滤是用“it.name”完成的)并且它可以工作,但是现在我正在尝试使其通用(T)与第二课(评论),我找不到办法做到...
我以为我可以传递一个与类相关的谓词,定义在过滤过程中如何匹配项目,但由于关键字仅在 performFiltering 方法中已知,因此我无法在此方法之外正确创建谓词...
我现在有点想不通了! 哈哈
你们有什么想法吗?
更新:按照@Tenfour04 的建议,我尝试将其调整为我的代码,该代码通过方法而不是使用构造函数传递过滤谓词,但除非我将“ActivyInfo::comments”替换为“ActivyInfo::comments.name”之类的内容,否则它不会编译" 但是我在调试中得到的 "searchedProperty(it)" 的值是 "name",它不是注释值。
这是代码:
注释适配器:
override fun getFilter(): Filter {
super.setFilter(
{ it.state != ProductState.HIDDEN },
{ ActivyInfo::comments },
compareBy<ProductInfo> { it.state }.thenBy(String.CASE_INSENSITIVE_ORDER) { it.name })
return super.getFilter()
}
基本适配器:
lateinit var defaultFilterPredicate : (T) -> Boolean
lateinit var searchedProperty : (T) -> CharSequence
lateinit var orderComparator : Comparator<T>
fun setFilter(defaultPredicate: (T) -> Boolean, property: (T) -> CharSequence, comparator: Comparator<T> ) {
defaultFilterPredicate = defaultPredicate
searchedProperty = property
orderComparator = comparator
}
override fun performFiltering(constraint: CharSequence): FilterResults {
...
filteredList = sourceList.filter {
constraintRegex.containsMatchIn(Normalizer.normalize(searchedProperty(it), Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
...
}
您可以向构造函数传递一个参数,该参数将属性指定为函数。
abstract class BaseFirestoreAdapter<T : BaseFirestoreAdapter.DataInterface, VH : RecyclerView.ViewHolder>(val filteredProperty: (T) -> CharSequence) : RecyclerView.Adapter<VH>(), Filterable
{
var sourceList: MutableList<T> = ArrayList()
// ...
override fun performFiltering(keyword: CharSequence): FilterResults {
val keywordRegex = keyword.toString().toRegex(setOf(RegexOption.IGNORE_CASE, RegexOption.LITERAL))
filteredList = sourceList.filter {
keywordRegex.containsMatchIn(Normalizer.normalize(filteredProperty(it), Normalizer.Form.NFD).replace("[^\\p{ASCII}]".toRegex(RegexOption.IGNORE_CASE), ""))
}
results.values = filteredList.sortedWith(orderComparator)
results.count = filteredList.size
}
...
}
我到你所做的更改是在加入的构造参数filteredProperty
,更改sourceList
类型T
,以及替换it.name
与filteredProperty(it)
。
所以子类必须调用这个超级构造函数,像这样传递属性:
data class SomeData(val comments: String)
class SomeDataAdapter: BaseFirestoreAdapter<SomeData>(SomeData::comments) {
//...
}
或者,如果您想保持通用:
class SomeDataAdapter(filteredProperty: (T) -> CharSequence): BaseFirestoreAdapter<SomeData>(filteredProperty) //...
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.