Kolin - 列表项目列表

时间:2016-11-07 16:46:55

标签: rx-java kotlin

我有一个对象列表,我想将其转换为以下类型的列表对象

data class Value(val x : Int, val y: Int)

到以下类型的对象:

data class Collection(val xs : List<Int>, val ys: List<Int>)

我正在寻找的东西类似于RxJava中的collect运算符,或者如果可能的话更好的方法。有谁有想法?

3 个答案:

答案 0 :(得分:3)

一个简单的解决方案是使用单独的map调用从xs获取ysValue

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包含只读列表,我没有看到构建它的简单方法,而不是首先列出列表,当然,不考虑像这样的表达但效率低下的功能解决方案,在每次迭代中复制xsys

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