问题
I'm wondering about methods of mapping multiple arrays into one list of object.
I mean e.g. I have
val a = arrayOf("A1","A2","A3")
val b = arrayOf("B1","B2","B3")
and
data class SomeClass(val v1:String, val v2:String)
I want to parse it in elegant way to have list like that:
val list = listOf(SomeClass("A1","B1"),SomeClass("A2","B2"),SomeClass("A3","B3"))
I assume they are of the same length. The only way I thought of is:
val list = mutableListOf<SomeClass>()
for (i in a.indices)
array.add(SomeClass(a[i],b[i])
Is there a better, more elegant solution (maybe using Collecions.zip or Array.map)?
回答1:
Try Array.zip and then map:
val list = a.zip(b)
.map { SomeClass(it.first, it.second) }
or if you like it more:
val list = a.zip(b)
.map { (a, b) -> SomeClass(a, b) }
Note that if both arrays differ in size, the additional values are ignored. Note also that this will create intermediate Pairs (which is the default transformation function of zip). Even though I like the explicit map more, @hotkeys solution regarding the overloaded method is more appropriate (you spare that hidden Pair-transformation):
val list = a.zip(b) { a, b -> SomeClass(a, b) }
And where the overloaded method probably shines, is when using references instead:
a.zip(b, ::SomeClass)
Which will work as long as you have a constructor matching the zipped arguments and doesn't work out of the box for the Pair (yet?).
回答2:
Improving on @Roland's answer, you can use the zip overload that accepts a two-argument function for mapping the pairs immediately:
val result = a.zip(b) { x, y -> SomeClass(x, y) }
回答3:
You can write some custom fun like this:
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
}
And use this transform for getting 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) }
来源:https://stackoverflow.com/questions/51766354/mapping-arrays-to-list-of-objects-kotlin