How to do a groupBy and collect using RxJava and Kotlin?

kotlin, reactive-programming, rx-java, rx-kotlin

Solution

Please look at the comments in the code for answers to your question.

import rx.Observable

fun main(args: Array<String>) {
    val service = Service()

    // This adds all keys with each key mapped to zero
    val referenceKeyCounts = Observable
        .just("1", "2", "3", "4", "5")
        .map { it to 0 }

    val keyCountsFromService = service.getRates()
        .flatMap { Observable.from(it.rates) }
        .filter { !it.value.isNullOrEmpty() }
        .map { it.value to 1 } // map each occurrence of key to 1

    Observable.concat(referenceKeyCounts, keyCountsFromService)
        .groupBy { it.first }
        .flatMap { group ->  // this converts GroupedObservable to final values
            group.reduce(0, { acc, pair -> acc + pair.second }) // add instead of counting
                .map { group.key to it }
        }
        .subscribe(::println)

}

class Service {
    fun getRates(): Observable<Rates> = Observable.just(Rates(listOf(
        Rate("1"), Rate("2"), Rate("3"), Rate("3"), Rate("2"), Rate("2")
    )))
}

class Rate(val value: String)

class Rates(val rates: List<Rate>)

Problem

I have got `Observable<Rates>` and Rate is just a simple object: ``` Rate(val value:String){} Rates(val rates: List<Rate>) ``` and i wanna change that `Observable<Rates>` into `Observable<HashMap<String,Long>`. so for example for rates `Rates(arrayOf(Rate("1"),Rate("2"), Rate("3"),Rate("3"), Rate("2"),Rate("2")))` i expect result: ``` (1 -> 1) (2 -> 3) (3 -> 2) (4 -> 0) (5 -> 0) ``` I start creating something like that : ``` service.getRates() .flatMap {it-> Observable.from(it.rates) } .filter { !it.value.isNullOrEmpty() } .groupBy {it -> it.value} .collect({ HashMap<String,Long>()}, { b, t -> b.put(t.key, t.count???)} ``` but I am stuck here and i do not know count all values? and i do not know how to add empty values (0) if there is no 5 of 4. Is there any way to do this using rx?

Original source