Kotlin flow: собирать только элементы, которые повторяются как минимум N раз

Я использую функцию распознавания символов ML Kit, и иногда первые несколько значений неверны, и только через некоторое время камера стабилизируется и выдает правильные значения. Я не хочу отбрасывать первые значения 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")
      }

1 ответ

Решение

Насколько я знаю, встроенного способа сделать это нет, но вы можете сделать это:

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.
        }
Другие вопросы по тегам