2016-11-07 2 views
3

у меня есть список объектов, которые я хочу, чтобы преобразовать в объект списков следующего типаKolin - Перечень элементов для элемента списков

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

на объект следующего вида:

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

То, что я ищу, похоже на оператор collect в RxJava или лучший способ сделать это, если это возможно. У кого-нибудь есть идеи?

ответ

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 s, вы можете использовать простой цикл 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

Спасибо. Я запустил все три, и метод карты занимает наименьшее количество времени для 100000 списка элементов. Я поставлю код запуска в отдельном ответе, чтобы люди могли проверить, выбирают ли они. –

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]) 

Но для этого конкретного случая проще всего сопоставить каждое положение toup ле.

val collection2 = Collection(values.map(Value::x), values.map(Value::y)) 
println(collection2) // => Collection(xs=[1, 3, 5], ys=[2, 4, 6]) 
0

Я использовал все методы, указанные в ответе @ hotkey, и метод карты является самым быстрым. Ниже приведен код, который я побежал:

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 
+0

Было бы здорово измерить производительность с помощью JMH – voddan

Смежные вопросы