Scala:如何解释foldLeft

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

我有两个

foldLeft
的例子,但我无法真正掌握其中的逻辑。

第一个例子:

val donuts: List[String] = List("Plain", "Strawberry", "Glazed")
println(donuts.foldLeft("")((acc, curr) =>  s" $acc, $curr Donut ")) // acc for accumulated, curr for current

这会给

 , Plain Donut , Strawberry Donut , Glazed Donut

foldLeft
不是积累之前的价值吗? 我期待的结果是

 , Plain Donut ,  Plain Strawberry Donut , Strawberry Glazed Donut

第二个例子:

def multi(num:Int,num1:Int):Int=num*10

(1 until 3).foldLeft(1)(multi)

有人可以解释一下每一步发生了什么吗?我不明白这怎么会变成 100。另外,第二个参数

multi
是一个函数。为什么它不接受任何输入变量(num 和 num1)?

scala higher-order-functions
2个回答
3
投票

不是

foldLeft
积累之前的价值吗?

是的,确实如此。它使用先前迭代和当前元素的结果并产生新结果(使用您提供的二元运算符),因此对于第一个示例,接下来的步骤正在发生:

  1. 累加器的起始值 -

    ""

  2. acc = ""
    ,
    curr = "Plain"
    ->
    " , Plain Donut "

  3. acc = " , Plain Donut "
    ,
    curr = "Strawberry"
    ->
    " , Plain Donut , Strawberry Donut "

  4. acc = " , Plain Donut , Strawberry Donut "
    ,
    curr = "Glazed"
    ->
    " , Plain Donut , Strawberry Donut , Glazed Donut "

对于第二个示例,当前值被简单地忽略 - 即

multi
可以重写为
def multi(acc:Int, curr:Int):Int = acc*10
,其中
curr
并未实际使用,因此
foldLeft
只需将起始值 (
1
) 乘以 10
n
倍,其中
n
是序列中的元素数量(即
(1 until 3).length
为 2)。

为什么它不接受任何输入变量(num 和 num1)?

foldLeft
是一个接受函数函数。它接受 一个 generic 函数,它依次接受两个参数并返回与第一个参数相同类型的结果(
op: (B, A) => B
,其中
B
是结果类型,
A
是序列元素类型)。当
multi
==
B
==
A
时,
Int
与此定义匹配,并传递给
foldLeft
,它将在内部提供每个步骤的输入变量。


0
投票

左折叠需要三件事:要处理的列表、初始值和函数。

该函数获取列表中的每个元素并将其应用于初始值。每次的初始值都是前一次函数应用的结果。

对列表求和是一个很好的玩具示例。

val nums = List(1, 2, 3, 4)
val total = nums.foldLeft(0)((a, b) => a + b)

total
10

初始值必须通过您需要的所有状态。目前,您传递累积的字符串。您应该传递的是一个 tuple ,为您的函数提供额外的信息以供使用:累积的字符串,以及表示列表中的 previous 元素的字符串。

您的结果将类似于:

("Plain donut, ...", "Glazed")

然后你只需要选择出累积的字符串并丢弃第二个元素即可。

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