I just want to add more general approach for situations where it is not possible to use fold(...)
. Because, in order to use fold
you need to be able to express some initial value.
someIterable
.filter { TODO("possibly filter-out everything") }
.takeIf { it.isNotEmpty() }
?.reduce { acc, element -> TODO("merge operation") }
?: TODO("value or exception for empty")
With this approach, in case of an empty collection, reduce
won't be executed because takeIf
will convert it to null
. And at the end we can use elvis operator to express some value (or throw exception) in that case.
Your example:
intArrayOf(1, 2, 3)
.filter { a -> a < 0 }
.takeIf { it.isNotEmpty() }
?.reduce { a, b -> a + b }
?: 0
EDIT:
Since kotlin 1.4, there is stdlib function reduceOrNull
which is more suitable than .takeIf { it.isNotEmpty() }
approach.
Generic case:
someIterable
.filter { TODO("possibly filter-out everything") }
.reduceOrNull { acc, element -> TODO("merge operation") }
?: TODO("value or exception for empty")
Used for your problem:
intArrayOf(1, 2, 3)
.filter { a -> a < 0 }
.reduceOrNull { a, b -> a + b }
?: 0