Kotlin中如何按name属性过滤嵌套对象列表?
解决Kotlin中嵌套列表的过滤问题
你应该是想过滤CategoryModel列表,让每个返回的CategoryModel只保留符合指定name子串的CollectionModel,同时得到处理后的完整CategoryModel列表对吧?你的原始代码问题在于,只是把整个原CategoryModel加入结果,但没有对内部的collections做过滤,所以才会出现"有两个元素时全部保留"的情况。
下面给你两种符合需求的实现方式:
方法一:Map + Filter(最直观易读)
这个方法分两步处理:
- 给每个
CategoryModel生成副本,将它的collections替换为过滤后符合条件的子列表 - (可选)过滤掉那些内部
collections为空的CategoryModel,避免保留没有有效内容的分类
// 注意:capitalize()已被弃用,推荐用replaceFirstChar实现首字母大写 val textToSearchCapitalized = textToSearch.replaceFirstChar { it.uppercase() } val filteredCategories = collection.map { category -> category.copy( collections = category.collections.filter { collectionModel -> collectionModel.name.contains(textToSearchCapitalized) } ) }.filter { it.collections.isNotEmpty() } // 这一步可选,根据需求决定是否保留空分类
为什么你的原始代码达不到预期?
你原来的循环逻辑是:只要找到一个符合条件的CollectionModel,就把整个原CategoryModel加入结果列表,但这个CategoryModel的collections还是原始的完整列表,并没有过滤掉不符合的元素,所以才会保留所有CollectionModel。
为什么reduce会报错?
reduce函数要求累积器的类型和当前元素的类型必须一致,你在代码里尝试把CategoryModel和List<CollectionModel>混合使用,类型不匹配,自然会编译报错。reduce更适合做累加、合并这类操作,并不适用于这种嵌套过滤的场景。
方法二:使用序列(Sequence)优化性能(数据量大时推荐)
如果你的列表数据量较大,可以用asSequence()来避免创建过多中间列表,提升处理性能:
val textToSearchCapitalized = textToSearch.replaceFirstChar { it.uppercase() } val filteredCategories = collection.asSequence() .map { category -> category.copy( collections = category.collections.filter { it.name.contains(textToSearchCapitalized) } ) } .filter { it.collections.isNotEmpty() } .toList()
内容的提问来源于stack exchange,提问作者S.P.
相关产品推荐
相关产品推荐

