首页 > 解决方案 > 如何在 Kotlin 中按名称属性过滤对象列表中的对象列表

问题描述

我正在尝试完成一项被证明很困难的任务。如何实现在 Kotlin 中过滤列表的目标?我在这里用过滤器和地图寻找,但不可能做到。

我有这个数据类。

data class CategoryModel(
    val collections: List<CollectionModel>,
    val id: Int,
    val name: String
)

data class CollectionModel(
    val id: Int,
    val image: String,
    val name: String
)

我想做的是获取一个 CategoryModel 列表,其中只有与特定 collectionModel.name 的子字符串匹配的 collectionModel。

这是我尝试过的代码,但是如果 collectionModel 有两个元素,我都会得到两个元素,并且我只想要包含子字符串的元素:

collection.forEachIndexed { index, element ->
    for (collectionModel in collection[index].collections) {
        if (collectionModel.name.contains(textToSearch.capitalize())) {
             collectionSearch.add(collection[index])
        }
    }
}
return collectionSearch

更新 1

collection.reduce{ acc, list ->  list.collections.filter { it.name.contains(textToSearch.capitalize()) } }

给出这个错误:

![图像错误

标签: androidkotlin

解决方案


这感觉有点 hacky,因为下面的代码创建了CategoryModel使用过滤列表的新对象CollectionModel,但它似乎工作。它返回一个MutableList<CategoryModel>因为

var collectionSearch: List<CategoryModel> = categoryModelList.filter {
    // check each CategoryModel
    categoryModel -> categoryModel.collections.filter {
        // check if there are CollectionModels with a name containing capitalized textToSearch
        collectionModel -> collectionModel.name.contains(textToSearch.capitalize())
    }.isNotEmpty() // only consider those with a non empty result
}.toList()  // get all the matching CategoryModels as List<CategoryModel>

fun main像这样称呼它

fun main() {
    // minimal data sample
    var categoryModelList: List<CategoryModel> = listOf(
        CategoryModel(listOf(CollectionModel(1, "collMod A", "nameA")), 1, "catMod A"),
        CategoryModel(listOf(CollectionModel(1, "collMod B", "nameB")), 2, "catMod B")
    );

    // sample text to be found
    val textToSearch: String = "b";

    // here it is
    var collectionSearch: List<CategoryModel> = categoryModelList.filter {
        categoryModel -> categoryModel.collections.filter {
            collectionModel -> collectionModel.name.contains(textToSearch.capitalize())
        }.isNotEmpty()
    }.toList()

    println(collectionSearch)
}

产生以下输出:

[CategoryModel(collections=[CollectionModel(id=1, image=collMod B, name=nameB)], id=2, name=catMod B)]

这似乎是需要的。

编辑

明确需求后,下面的扩展功能List<CategoryModel>可能就足够了,虽然感觉不完美:

fun List<CategoryModel>.getModified(condition: String): List<CategoryModel> {
    var result: MutableList<CategoryModel> = mutableListOf();

    this.forEach { categoryModel ->
        // get a list of matching CollectionModels
        val cols = categoryModel.collections.filter { collectionModel ->
            collectionModel.name.contains(condition.capitalize())
        }
        // if the list is not empty
        if (cols.isNotEmpty()) {
            /*
             * add a new item to the result using the filtered collections
             * and the other (unmodified) attributes
             */
            result.add(CategoryModel(cols, categoryModel.id, categoryModel.name))
        }
    }

    return result
}

当我这样称呼它时

fun main() {
    // minimal data sample
    var categoryModelList: List<CategoryModel> = listOf(
        CategoryModel(mutableListOf(CollectionModel(1, "collMod A", "nameA"),
                            CollectionModel(2, "collMod B", "nameB")
                            ), 1, "catMod 1"),
        CategoryModel(mutableListOf(CollectionModel(3, "collMod B", "nameB")), 2, "catMod 2"),
        CategoryModel(mutableListOf(CollectionModel(4, "collMod BB", "nameBB"),
                            CollectionModel(5, "collMod C", "nameC")
                            ), 3, "catMod 3"),
        CategoryModel(mutableListOf(CollectionModel(6, "collMod A", "nameA"),
                            CollectionModel(7, "collMod D", "nameD")
                            ), 4, "catMod 4")
    );

    // sample text to be found
    val textToSearch: String = "b";
    // print the source
    println(categoryModelList)
    // and the modified list in order to compare them
    println(categoryModelList.getModified(textToSearch))
}

输出似乎是所需的:

[CategoryModel(collections=[CollectionModel(id=1, image=collMod A, name=nameA), CollectionModel(id=2, image=collMod B, name=nameB)], id=1, name=catMod 1), CategoryModel(collections=[CollectionModel(id=3, image=collMod B, name=nameB)], id=2, name=catMod 2), CategoryModel(collections=[CollectionModel(id=4, image=collMod BB, name=nameBB), CollectionModel(id=5, image=collMod C, name=nameC)], id=2, name=catMod 3), CategoryModel(collections=[CollectionModel(id=6, image=collMod A, name=nameA), CollectionModel(id=7, image=collMod D, name=nameD)], id=3, name=catMod 4)]
[CategoryModel(collections=[CollectionModel(id=2, image=collMod B, name=nameB)], id=1, name=catMod 1), CategoryModel(collections=[CollectionModel(id=3, image=collMod B, name=nameB)], id=2, name=catMod 2), CategoryModel(collections=[CollectionModel(id=4, image=collMod BB, name=nameBB)], id=2, name=catMod 3)]

这意味着只剩CategoryModel下匹配CollectionModels 的 scollections并且只剩下那些,所有其他的都已被删除。


推荐阅读