Стрелка Kotlin преобразовывает Список сбоев в Сбой списка
Как я могу преобразовать следующее:
List<Try<String>>
чтобы:
Try<List<String>>
Использование котлина и функциональной библиотеки стрелка (0.8.2). Я хотел бы обернуть это в пользовательское исключение. Неважно, какой из "String" потерпел неудачу.
Обновить:
Поскольку приведенных ниже ответов будет достаточно, но я нахожу это действительно трудно читать. Итак, я реализовал следующее:
Создайте следующую функцию:
fun getFailedStrings(result: List<Try<String>>): List<Failure> {
return result.fold(
initial = listOf(),
operation = { accumulator, nextUpdate ->
nextUpdate.fold(
ifSuccess = { accumulator },
ifFailure = { accumulator + Failure(it) }
)
})
}
Затем используйте результат функции:
return if (failedStrings.isNotEmpty()) {
failedStrings.first() // or whatever fits your usecase
} else {
// strings is the initial result of List<Try<String>>
Success(strings.mapNotNull { it.orNull() })
}
2 ответа
Если мы не заботимся о сохранении исходных исключений, мы можем сделать что-то вроде этого с помощью traverse:
val traversedTries = tries.traverse(Try.applicative(), ::identity)
Это вернет экземпляр типа Try<ListK<String>>
либо со всеми строками, либо с первым найденным исключением.
ListK
простирается от List
но мы можем при желании разыграть его, добавив .map { it as List<String> }
в конце концов, если нам нужно, чтобы это было Try<List<String>>
В качестве альтернативы, если мы хотим разделить успехи и неудачи, мы можем создать следующую функцию:
fun <A> List<Try<A>>.splitSuccessFailure() : Tuple2<List<A>, List<Throwable>> =
fold(emptyList<A>() toT emptyList<Throwable>()) { (successes, failures), it ->
it.fold({ successes toT (failures + it) }, { (successes + it) toT failures })
}
Затем, когда мы хотим использовать его, мы можем сделать следующее:
val (successes, failures) = invalidTries.splitSuccessFailure()
Предоставляя нам два списка со значениями успеха и неудач соответственно.
Это похоже на работу:
fun convert(input: List<Try<String>>): Try<List<String>> =
input.fold(Try.just(emptyList())) { acc, i ->
acc.flatMap { list ->
i.flatMap {
Try.just(list + it)
}
}
}