当前位置: 首页 > 知识库问答 >
问题:

Kotlin中折叠和缩小的区别,何时使用哪种?

谭昊乾
2023-03-14

我对Kotlin中的两个函数fold()reduce()感到非常困惑,有人能给我一个具体的例子来区分这两个函数吗?

共有3个答案

公孙阳羽
2023-03-14

其他答案都没有提到的另一个区别是:

reduce操作的结果将始终与被缩减的数据属于同一类型(或超级类型)。从reduce方法的定义可以看出:

public inline fun <S, T : S> Iterable<T>.reduce(operation: (acc: S, T) -> S): S {
    val iterator = this.iterator()
    if (!iterator.hasNext()) throw UnsupportedOperationException("Empty collection can't be reduced.")
    var accumulator: S = iterator.next()
    while (iterator.hasNext()) {
        accumulator = operation(accumulator, iterator.next())
    }
    return accumulator
}

另一方面,折叠操作的结果可以是任何东西,因为在设置初始值时没有限制。所以,例如,让我们假设我们有一个包含字母和数字的字符串。我们想计算所有数字的总和。我们可以很容易地用折叠来做到这一点:

val string = "1a2b3"
val result: Int = string.fold(0, { currentSum: Int, char: Char ->
    if (char.isDigit())
        currentSum + Character.getNumericValue(char)
    else currentSum
})

//result is equal to 6
吕胤
2023-03-14

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

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

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

将此与进行对比。折叠,这要求您提供一个“起始值”,如果集合为空,它将是默认值:

val result = listOf<Int>().fold(0) { x, y -> x + y }
assertEquals(0, result)

因此,即使您不想将集合聚合为不同(非相关)类型的单个元素(只有.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)

孟安民
2023-03-14

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

 类似资料:
  • 和是否具有相同的功能,只是语法不同,或者和之间是否存在重大差异? 哪一种是正确的方法?

  • 我有一个JScrollPane,其中包含一个JTextArea。当窗口最小化然后恢复时,JScrollPane将自行崩溃。注意,只有当JTextArea中的文本超过JTextArea的给定宽度和/或高度(即,出现水平或垂直滚动条)时,才会发生挤压。 这里的问题:JScrollpane在最小化后失去大小会带来同样的问题,但是这个问题从未得到解决,除了向JScrollPane添加权重、权重和填充约束,

  • 这个链接!告诉我如何禁用折叠工具栏布局。我想要的行为是折叠并禁用折叠工具栏,并在没有internet连接时显示错误视图。那么我如何才能做到这一点,折叠和禁用折叠工具栏布局?

  • 我在寻找一种在Atom中使用C#regions之类的东西折叠JavaScript代码的方法: 我找不到这样的包裹。我知道你可以按CTRLAltF折叠所选代码。但我想要命名区域。 所以真正的问题是,有人知道我如何在原子中做到这一点吗? 谢谢

  • 我正在尝试在我的android应用程序中实现折叠工具栏。我可以按我希望的方式显示工具栏,但滚动时它不会塌陷。 我正在使用以下代码 activity.xml main_toolbar.xml 下面是屏幕的外观

  • Jar和java中的插件有什么区别?两者看起来是一样的,因为实现了相同的目的,什么时候使用Jar和什么时候使用插件。