我正在学习Scala,并对简单问题的输出感到困惑 在范围之间找到偶数整数的平方和。
代码段1 :
val rangeOfNumbers = (1 to 5)
val listOfNumbers = rangeOfNumbers.toList
val squaresOfEvenNumbers = listOfNumbers
.filter(element => element % 2 == 0)
.reduce((total, element) => total+ (element * element))
println(squaresOfEvenNumbers)
Outputs: 18 -> which is clearly wrong
**EDIT** - Simulation:
I want to square the filtered even numbers - 2,4 and then add them to total variable
1: (total = 0, elem = 2) => 0 + (2 * 2) = 4
2. (total = 4, elem = 4) => 4 + (4 *4 ) = 20
Isn't this the expected behavior?
代码段2 :
val rangeOfNumbers = (1 to 5)
val listOfNumbers = rangeOfNumbers.toList
val filteredEvenNumberSquaredList = listOfNumbers
.filter(element => element % 2 == 0)
.map(evenEle => evenEle * evenEle)
.reduce((total, square) => total + square)
println(filteredEvenNumberSquaredList)
Outputs: 20 -> which is correct
你能解释第一种方法有什么问题吗?内部发生了什么?
答案 0 :(得分:3)
在第一次调用lambda时,传递给.reduce
,total
是列表的第一个元素,element
是第二个元素。你不会对前者产生影响,只有后者,所以你的结果是2。
您可能需要考虑使用.foldLeft
而不是reduce
:
list.foldLeft(0) { case (sum, elem) => sum + elem*elem }
它与.reduce
相同,除了它以您提供的值(在本例中为0
)开头,并且对于列表的每个元素都以相同的方式调用,包括第一个一个(它也适用于空列表,而.reduce
会崩溃)。
或者,只需list.map(x => x*x).sum
val squaresOfEvenNumbers = (1 to 5)
.collect { case x if x % 2 == 0 => x*x }
.sum
答案 1 :(得分:1)
当您使用List(2, 4).reduce((sum, el) => sum + el * el)
=> 2 + 4 * 4
=> 18
时,加倍并不适用于第一个元素:
reduce
l.reduce(op) == l.tail.foldLeft(l.head)(op)
(对于非空列表)应满足:
tf.map_fn