Kotlin 流程:仅收集至少重复 N 次的元素
Kotlin flow: collect only elements which repeat at least N times
我正在实现 ML Kit OCR 功能,有时前几个值是错误的,只有在一段时间后相机稳定并产生正确的值。我不想删除第一个 X 值,因为我不知道流程将包含多少元素。所以最好的方法是使用一些条件,将当前元素与前一个元素进行比较,但不确定。
Kotlin Flow API 中是否有一个函数可以比较收集到的值并只收集至少出现 N 次的值?
private val _detectedValues = ConflatedBroadcastChannel<String>()
val detectedFlow = _detectedValues
.asFlow()
.map { it.replace(" ", "") }
.filter { it.checkRegex() }
.onEach {
Log.i(TAG, "detected: $it")
}
据我所知,没有内置的方法可以做到这一点,但你可以做一个:
fun <T> Flow<T>.repeated(times: Int): Flow<T> {
val map = mutableMapOf<T, Int>()
return transform { value ->
val count = (map[value] ?: 0) + 1
map[value] = count
if (count >= times) {
return@transform emit(value)
}
}
}
这使用映射来跟踪每个值已发出的次数。然后,如果一个值被发出足够多次,它就会通过转换发出。
channel.asFlow()
.repeated(3)
.collect {
// Do something.
}
编辑: 它绝对有效。这是测试代码:
suspend fun test() = coroutineScope {
val flow = MutableSharedFlow<String>()
launch {
flow.repeated(3).collect { value ->
println("received: $value")
}
}
launch {
while (true) {
val value = listOf("a", "b", "c").random()
println("emitted: $value")
flow.emit(value)
delay(1000)
}
}
}
我得到以下输出:
emitted: c
emitted: a
emitted: c
emitted: c
received: c
emitted: b
emitted: b
emitted: b
received: b
emitted: a
emitted: a
received: a
emitted: a
received: a
emitted: b
received: b
我正在实现 ML Kit OCR 功能,有时前几个值是错误的,只有在一段时间后相机稳定并产生正确的值。我不想删除第一个 X 值,因为我不知道流程将包含多少元素。所以最好的方法是使用一些条件,将当前元素与前一个元素进行比较,但不确定。
Kotlin Flow API 中是否有一个函数可以比较收集到的值并只收集至少出现 N 次的值?
private val _detectedValues = ConflatedBroadcastChannel<String>()
val detectedFlow = _detectedValues
.asFlow()
.map { it.replace(" ", "") }
.filter { it.checkRegex() }
.onEach {
Log.i(TAG, "detected: $it")
}
据我所知,没有内置的方法可以做到这一点,但你可以做一个:
fun <T> Flow<T>.repeated(times: Int): Flow<T> {
val map = mutableMapOf<T, Int>()
return transform { value ->
val count = (map[value] ?: 0) + 1
map[value] = count
if (count >= times) {
return@transform emit(value)
}
}
}
这使用映射来跟踪每个值已发出的次数。然后,如果一个值被发出足够多次,它就会通过转换发出。
channel.asFlow()
.repeated(3)
.collect {
// Do something.
}
编辑: 它绝对有效。这是测试代码:
suspend fun test() = coroutineScope {
val flow = MutableSharedFlow<String>()
launch {
flow.repeated(3).collect { value ->
println("received: $value")
}
}
launch {
while (true) {
val value = listOf("a", "b", "c").random()
println("emitted: $value")
flow.emit(value)
delay(1000)
}
}
}
我得到以下输出:
emitted: c
emitted: a
emitted: c
emitted: c
received: c
emitted: b
emitted: b
emitted: b
received: b
emitted: a
emitted: a
received: a
emitted: a
received: a
emitted: b
received: b