我有两个
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)?
不是
积累之前的价值吗?foldLeft
是的,确实如此。它使用先前迭代和当前元素的结果并产生新结果(使用您提供的二元运算符),因此对于第一个示例,接下来的步骤正在发生:
累加器的起始值 -
""
acc = ""
, curr = "Plain"
-> " , Plain Donut "
acc = " , Plain Donut "
, curr = "Strawberry"
-> " , Plain Donut , Strawberry Donut "
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
,它将在内部提供每个步骤的输入变量。
左折叠需要三件事:要处理的列表、初始值和函数。
该函数获取列表中的每个元素并将其应用于初始值。每次的初始值都是前一次函数应用的结果。
对列表求和是一个很好的玩具示例。
val nums = List(1, 2, 3, 4)
val total = nums.foldLeft(0)((a, b) => a + b)
total
是10
。
初始值必须通过您需要的所有状态。目前,您传递累积的字符串。您应该传递的是一个 tuple ,为您的函数提供额外的信息以供使用:累积的字符串,以及表示列表中的 previous 元素的字符串。
您的结果将类似于:
("Plain donut, ...", "Glazed")
然后你只需要选择出累积的字符串并丢弃第二个元素即可。