我想知道将多个数组映射到一个对象列表的方法。
我的意思是我有
val a = arrayOf("A1","A2","A3")
val b = arrayOf("B1","B2","B3")
和
data class SomeClass(val v1:String, val v2:String)
我想用一种优雅的方式来解析它,以获得这样的列表:
val list = listOf(SomeClass("A1","B1"),SomeClass("A2","B2"),SomeClass("A3","B3"))
我认为它们的长度相同。我想到的唯一方法是:
val list = mutableListOf<SomeClass>()
for (i in a.indices)
array.add(SomeClass(a[i],b[i])
是否有更好,更优雅的解决方案(也许使用Collecions.zip或Array.map)?
答案 0 :(得分:6)
先尝试Array.zip
,然后再尝试map
:
val list = a.zip(b)
.map { SomeClass(it.first, it.second) }
或者如果您更喜欢它:
val list = a.zip(b)
.map { (a, b) -> SomeClass(a, b) }
请注意,如果两个数组的大小均不同,则其他值将被忽略。还要注意,这将创建中间Pair
(这是zip
的默认转换函数)。尽管我更喜欢显式的map
,但有关重载方法的@hotkeys解决方案更合适(您可以保留隐藏的Pair
转换):
val list = a.zip(b) { a, b -> SomeClass(a, b) }
当使用引用代替时,重载方法可能发光的地方:
a.zip(b, ::SomeClass)
只要您有一个与压缩参数匹配的构造函数并且对于Pair
来说,它是开箱即用的,那将是可行的。
答案 1 :(得分:2)
在@Roland's answer上进行了改进,您可以使用zip
重载,该重载接受两个参数的函数来立即映射对:
val result = a.zip(b) { x, y -> SomeClass(x, y) }
答案 2 :(得分:0)
您可以像这样编写一些自定义乐趣:
inline fun <T, R, E, V> Iterable<T>.zipThree(other1: Iterable<R>, other2: Iterable<E>, transform: (T, R, E) -> V): List<V> {
val first = iterator()
val second = other1.iterator()
val third = other2.iterator()
val list = ArrayList<V>()
while (first.hasNext() && second.hasNext()) {
list.add(transform(first.next(), second.next(), third.next()))
}
return list
}
并使用此转换获取列表
val strings = listOf("1", "2")
val ints = listOf(1, 2)
val boolean = listOf(true, false)
val listYoutObjects = strings.zipThree(ints, boolean) { one, two, three -> YouObject(one, two, three) }