Kotlin中fold和reduce之间的基本区别是什么?什么时候用哪个?

问题描述 投票:71回答:2

我正在阅读Kotlin的基础知识,我对Kotlin中的函数fold()和reduce()非常困惑,有人能给我一个区分两者的具体例子吗?

kotlin reduce fold
2个回答
169
投票

fold取一个初始值,并且传递给它的lambda的第一次调用将接收该初始值,并将该集合的第一个元素作为参数。

例如,使用以下代码计算整数列表的总和:

listOf(1, 2, 3).fold(0) { sum, element -> sum + element }

第一次调用lambda将使用参数01

如果必须为操作提供某种默认值或参数,则能够传入初始值非常有用。例如,如果您在列表中查找最大值,但由于某种原因想要返回至少10,您可以执行以下操作:

listOf(1, 6, 4).fold(10) { max, element ->
    if (element > max) element else max
}

reduce不接受初始值,而是从集合的第一个元素开始作为累加器(在下面的示例中称为sum)。

例如,让我们再做一次整数:

listOf(1, 2, 3).reduce { sum, element -> sum + element }

这里对lambda的第一次调用将使用参数12

当您的操作不依赖于您正在应用它的集合中的值以外的任何值时,您可以使用reduce


2
投票

我要提出的主要功能差异(在另一个答案的评论中提到,但可能很难理解)是reduce如果在空集合上执行将抛出异常。

listOf<Int>().reduce { x, y -> x + y }
// java.lang.UnsupportedOperationException: Empty collection can't be reduced.

这是因为.reduce不知道在“无数据”的情况下返回什么值。

.fold相比,val result = listOf<Int>().fold(0) { x, y -> x + y } assertEquals(0, result) 要求您提供“起始值”,这将是空集合时的默认值:

.fold

因此,即使您不想将您的集合汇总到一个不同(非相关)类型的单个元素(只有.reduce可以让您这样做),如果您的起始集合可能是空的,那么您必须检查您的收集大小首先,然后.fold,或只是使用val collection: List<Int> = // collection of unknown size val result1 = if (collection.isEmpty()) 0 else collection.reduce { x, y -> x + y } val result2 = collection.fold(0) { x, y -> x + y } assertEquals(result1, result2)

qazxswpoi
© www.soinside.com 2019 - 2024. All rights reserved.