如何用Kotlin解构声明在单次集合遍历中获取多个属性列表?
Kotlin 单次遍历提取集合多属性的实现方案
问题场景
现有业务场景如下:
data class Person(val name: String, val age: String, val color: String) val persons = listOf(Person("john", "20", "green"), Person("Mary", "20", "blue")) // 现有实现问题: // 1. 调用3次map需遍历3次集合 val names = persons.map {it.name} val ages = persons.map {it.age} val colors = persons.map {it.color} // 2. unzip仅支持单次遍历提取2个属性 val personsMap = persons.map { it.name to it.age } val (names2, ages2) = personsMap.unzip() // 需求:无需手动写forEach往列表追加元素,单次遍历同时提取3个属性,支持解构语法赋值 // val (names, ages, colors) = 单次遍历逻辑
实现方案
- 方案1:用标准库原生
fold函数实现,无需额外自定义逻辑
val (names, ages, colors) = persons.fold( Triple(mutableListOf<String>(), mutableListOf<String>(), mutableListOf<String>()) ) { acc, person -> acc.first.add(person.name) acc.second.add(person.age) acc.third.add(person.color) acc }
说明:fold 函数会在单次遍历中完成所有元素的聚合,最终返回的Triple直接支持解构,代码写法简洁,适合临时单次使用的场景。
- 方案2:自定义通用
unzip3扩展函数,适合高频复用场景
首先定义全局通用扩展:
/** * 三属性解压扩展,逻辑与原生unzip对齐,单次遍历返回三个独立列表 */ fun <T, A, B, C> Iterable<T>.unzip3(transform: (T) -> Triple<A, B, C>): Triple<List<A>, List<B>, List<C>> { val listA = mutableListOf<A>() val listB = mutableListOf<B>() val listC = mutableListOf<C>() for (item in this) { val (a, b, c) = transform(item) listA.add(a) listB.add(b) listC.add(c) } return Triple(listA.toList(), listB.toList(), listC.toList()) }
业务侧调用方式:
val (names, ages, colors) = persons.unzip3 { Triple(it.name, it.age, it.color) }
说明:扩展函数封装后调用逻辑和原生unzip保持一致,无冗余代码,适合项目中多处需要多属性提取的场景。
- 方案3:使用kotlinx.collections.immutable库自带的unzip3实现
如果项目已经引入了kotlinx不可变集合依赖,可直接使用库中提供的unzip3扩展,用法和上述自定义扩展完全一致,无需自行实现扩展逻辑。
内容的提问来源于stack exchange,提问作者En Hui Lim
相关产品推荐
相关产品推荐

