我有一个对象列表,我想将其转换为以下类型的列表对象
data class Value(val x : Int, val y: Int)
到以下类型的对象:
data class Collection(val xs : List<Int>, val ys: List<Int>)
我正在寻找的东西类似于RxJava中的collect
运算符,或者如果可能的话更好的方法。有谁有想法?
答案 0 :(得分:3)
一个简单的解决方案是使用单独的map
调用从xs
获取ys
和Value
:
fun collectionOf(values: List<Value>) =
Collection(values.map { it.x },
values.map { it.y })
用法示例:
val values = listOf(Value(1, 2), Value(3, 4))
val collection = collectionOf(values) // Collection(xs=[1, 3], ys=[2, 4])
如果您希望在Value
的单次迭代中执行此操作,则可以使用简单的for
循环:
fun collectionOf(values: List<Value>) {
val xs = mutableListOf<Int>()
val ys = mutableListOf<Int>()
for ((x, y) in values) {
xs.add(x)
ys.add(y)
}
return Collection(xs, ys)
}
由于Collection
包含只读列表,我没有看到构建它的简单方法,而不是首先列出列表,当然,不考虑像这样的表达但效率低下的功能解决方案,在每次迭代中复制xs
和ys
:
fun collectionOf(values: List<Value>) =
values.fold(Collection(listOf(), listOf())) { acc, it ->
Collection(acc.xs + it.x, acc.ys + it.y)
}
答案 1 :(得分:1)
收藏家的等价物是fold
val values = listOf(Value(1,2), Value(3,4), Value(5,6))
val collection =
values.fold(Collection(listOf(), listOf()))
{ acum, value -> Collection(acum.xs + value.x, acum.ys + value.y)}
println(collection) // => Collection(xs=[1, 3, 5], ys=[2, 4, 6])
但是对于这种特殊情况来说,只需映射一下这个位置的每个位置就更简单了。
val collection2 = Collection(values.map(Value::x), values.map(Value::y))
println(collection2) // => Collection(xs=[1, 3, 5], ys=[2, 4, 6])
答案 2 :(得分:0)
我运行了@ hotkey的答案中提供的所有方法,并且map方法是最快的。以下是我运行的代码:
data class Value(val x : Int, val y: Int)
data class Collection(val xs : List<Int>, val ys: List<Int>)
fun collectionOf(values: List<Value>): Collection {
val xs = mutableListOf<Int>()
val ys = mutableListOf<Int>()
for ((x, y) in values) {
xs.add(x)
ys.add(y)
}
return Collection(xs, ys)
}
var startTime = System.currentTimeMillis()
(1..100000).map { Value(it * 1, it * 3) }.fold(Collection(listOf(), listOf()), { acc, value -> Collection(acc.xs + value.x, acc.ys + value.y) })
println("Fold takes: " + (System.currentTimeMillis() - startTime))
startTime = System.currentTimeMillis()
(1..100000).map { Value(it * 1, it * 3) }.let { Collection(it.map { it.x }, it.map { it.y }) }
println("\nMap takes: " + (System.currentTimeMillis() - startTime))
startTime = System.currentTimeMillis()
collectionOf((1..100000).map { Value(it * 1, it * 3) })
println("\nCollection takes: " + (System.currentTimeMillis() - startTime))
示例输出为:
Fold takes: 12776
Map takes: 12
Collection takes: 29