Scala:如何解释 foldLeft
Scala: How to interpret foldLeft
我有两个例子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)?
Does not foldLeft
accumulate value that was earlier?
是的。它 uses 先前迭代和当前元素的结果并产生新结果(使用您提供的二元运算符)因此对于第一个示例,接下来的步骤正在发生:
累加器起始值 - ""
acc = ""
, curr = "Plain"
-> " , Plain Donut "
acc = " , Plain Donut "
, curr = "Strawberry"
-> " , Plain Donut , Strawberry Donut "
acc = " , Plain Donut , Strawberry Donut "
, curr = "Strawberry"
-> " , 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)。
Why does it not take any input variables (num and num1)?
foldLeft
is a function which accepts a function。它接受
generic 函数依次接受两个参数和与第一个参数类型相同的 returns 结果(op: (B, A) => B
,其中 B
是结果类型,A
是序列元素类型)。当 B
== A
== Int
时 multi
匹配此定义并传递给 foldLeft
,后者将在每个步骤内部提供输入变量。
左折叠需要三样东西:要处理的列表、初始值和函数。
该函数获取列表中的每个元素并将其应用于初始值。每次的初始值都是上一次函数应用的结果
总结列表是一个很好的玩具示例。
val nums = List(1, 2, 3, 4)
val total = nums.foldLeft(0)((a, b) => a + b)
total
是 10
。
该初始值必须通过您需要的所有状态。目前,您传递了累积的字符串。你应该传递的是一个 tuple 给你的函数额外的信息来处理:累积的字符串,和一个代表 previous 元素的字符串列表。
您的结果将类似于:
("Plain donut, ...", "Glazed")
那么你只需要select取出累积的字符串并丢弃第二个元素。
我有两个例子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)?
Does not
foldLeft
accumulate value that was earlier?
是的。它 uses 先前迭代和当前元素的结果并产生新结果(使用您提供的二元运算符)因此对于第一个示例,接下来的步骤正在发生:
累加器起始值 -
""
acc = ""
,curr = "Plain"
->" , Plain Donut "
acc = " , Plain Donut "
,curr = "Strawberry"
->" , Plain Donut , Strawberry Donut "
acc = " , Plain Donut , Strawberry Donut "
,curr = "Strawberry"
->" , 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)。
Why does it not take any input variables (num and num1)?
foldLeft
is a function which accepts a function。它接受
generic 函数依次接受两个参数和与第一个参数类型相同的 returns 结果(op: (B, A) => B
,其中 B
是结果类型,A
是序列元素类型)。当 B
== A
== Int
时 multi
匹配此定义并传递给 foldLeft
,后者将在每个步骤内部提供输入变量。
左折叠需要三样东西:要处理的列表、初始值和函数。
该函数获取列表中的每个元素并将其应用于初始值。每次的初始值都是上一次函数应用的结果
总结列表是一个很好的玩具示例。
val nums = List(1, 2, 3, 4)
val total = nums.foldLeft(0)((a, b) => a + b)
total
是 10
。
该初始值必须通过您需要的所有状态。目前,您传递了累积的字符串。你应该传递的是一个 tuple 给你的函数额外的信息来处理:累积的字符串,和一个代表 previous 元素的字符串列表。
您的结果将类似于:
("Plain donut, ...", "Glazed")
那么你只需要select取出累积的字符串并丢弃第二个元素。