使用谓词的通用集合过滤

问题描述 投票:0回答:1

我在kotlin中遇到了有关集合过滤的棘手问题...

我有一个管理项目列表的基类,我希望能够用关键字过滤列表,所以我用Filterable方法扩展了该类。

我想做的就是能够使用此'基类'扩展多个类,因此所有类的过滤器机制都是相同的。

这些类没有相同的属性...在一个类中,必须根据是否在“名称”中找到关键字来进行过滤,而在另一个类中,对“ comment”属性进行过滤。

这里有一些代码:

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方法中是已知的,因此我无法在此方法之外正确地创建谓词...

我有点想法了!大声笑

您有任何想法吗?


UPDATE:按照@ Tenfour04的建议,我尝试将其调整为适合我的代码的代码,该代码通过方法而不是使用构造函数通过过滤谓词,但除非将“ ActivyInfo :: comments”替换为“ ActivyInfo :: comments.name”,然后我在调试中为“ searchedProperty(it)”获得的值是“名称”,而不是注释值。

这里是代码:

CommentAdapter:

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()
}

BaseAdapter:

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), ""))
        }

        ...

    }
java kotlin filter collections predicate
1个回答
0
投票

您可以向构造函数传递一个将属性指定为函数的参数。

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) //...
© www.soinside.com 2019 - 2024. All rights reserved.