Kotlin实用技巧:将扁平对象列表转为按年龄分组的映射
解决Kotlin列表按年龄分组为姓名列表的问题
嘿,你要的这个需求用Kotlin标准库的groupBy方法就能轻松搞定,这比associate/associateBy更适合这种一对多的分组场景,我给你一步步拆解:
首先,先回顾你的原始数据:
data class Someone(var name: String, var age: Int) val someoneList = listOf<Someone>(Someone("Joe", 12), Someone("Bill", 15), Someone("Nancy", 12))
直接得到按年龄分组的姓名列表
groupBy方法支持同时指定键选择器和值转换规则,一步就能得到你想要的Map<Int, List<String>>:
val ageToNamesMap = someoneList.groupBy( keySelector = { it.age }, // 用age作为映射的键 valueTransform = { it.name } // 把每个Someone对象转换成对应的name )
执行后结果就是:
{12=[Joe, Nancy], 15=[Bill]}
为什么不用associate/associateBy?
你提到的associate/associateBy其实是为一对一映射设计的:
associateBy会在遇到重复键时,用后面的元素覆盖前面的元素,比如如果用它处理你的列表,age=12对应的最终值只会是Nancy,而不是包含Joe和Nancy的列表。- 它们无法自动收集相同键的元素到列表中,完全不符合你要的分组需求。
分步实现(如果需要保留中间结果)
如果你先想得到按年龄分组的Someone列表,之后再转换成姓名列表,也可以分两步:
// 第一步:按年龄分组得到Someone对象的列表 val ageToPeopleMap = someoneList.groupBy { it.age } // 结果:{12=[Someone(name=Joe, age=12), Someone(name=Nancy, age=12)], 15=[Someone(name=Bill, age=15)]} // 第二步:把每个分组的Someone列表转换成姓名列表 val ageToNamesMap = ageToPeopleMap.mapValues { (_, people) -> people.map { it.name } }
这样就完全满足你的需求啦,Kotlin的标准库在集合操作上确实很简洁,找对方法就事半功倍~
内容的提问来源于stack exchange,提问作者vrfrom07
相关产品推荐
相关产品推荐

