如何做一个组,并使用RxJava和Kotlin收集?
我有Observable
和Rate是一个简单的对象:
Rate(val value:String){} Rates(val rates: List)
我想将Observable
改为Observable<HashMap
。
Rates(arrayOf(Rate("1"),Rate("2"), Rate("3"),Rate("3"), Rate("2"),Rate("2")))
我期望的结果:
(1 -> 1) (2 -> 3) (3 -> 2) (4 -> 0) (5 -> 0)
我开始创建这样的东西:
service.getRates() .flatMap {it-> Observable.from(it.rates) } .filter { !it.value.isNullOrEmpty() } .groupBy {it -> it.value} .collect({ HashMap()}, { b, t -> b.put(t.key, t.count???)}
但我卡在这里,我不知道所有的价值? 我不知道如何添加空值(0),如果没有5个4.有没有办法使用rx做到这一点?
请查看代码中的注释以解答您的问题。
import rx.Observable fun main(args: Array) { 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 = 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)
诀窍是在GroupedObservable
上使用count
,因为它只在源observable完成时才发出单个值:
从那里:
rates .flatMap { Observable.from(it.rates) } .filter { !it.value.isNullOrEmpty() } .groupBy { it.value } .flatMap { group -> group.count().map { group.key to it } } // list "1"->1, "2"->3, ... .mergeWith(Observable.from((1..5).map { it.toString() to 0 })) // defaults "4"->0 .reduce(mutableMapOf()) { acc, cur -> acc.apply { val (key, count) = cur this[key] = (this[key] ?: 0) + count // add counts } }.subscribe { countedRates -> println(countedRates) }
我认为这更多是关于函数式编程而不是RxJava相关的问题
从Rates -> Map
实现一个映射函数。
技巧:合并Pair
两个列表以形成一个Map
val ratesToMapWithEmptyValues: (Rates) -> Map = { source -> //TODO: Just for demo val validRatesValue = arrayOf("1","2","3","4","5") mapOf( *validRatesValue.map { it to 0 }.toTypedArray(), *source.rates.groupBy(Rate::value).mapValues { it.value.size }.toList().toTypedArray() ) }
在Observable.map
应用该函数
service.getRates() .map(ratesToMapWithEmptyValues)
- Java中的Kotlingenerics错误
- 使用Fuel和Result将字节数组转换为Json
- kotlin集合将一个Map转换为一个新的Map,其中的值由原始值计算得出
- Kotlin / Native是否可以使用?
- 测试JOOQ postgres jsonb列键是否存在
- 使用Retrofit 2和Kotlin获取错误的原始HTML / JSON响应
- 在Kotlin中计算移动平均的最快/最简单的方法是什么?
- Kotlin使用Room persistence lib进行代理
- 从Java转换到Kotlin时出错。 错误 – org.gradle.api.tasks.TaskExecutionException:任务执行失败:app:compileDebugKotlin'