Scala:列表中带有负数的 foldLeft 问题
Scala: Problem with foldLeft with negative numbers in list
我正在编写一个 Scala 函数,它 returns 列表中偶数元素的总和减去列表中奇数元素的总和。我不能为我的解决方案使用可变、递归或 for/while 循环。下面的代码通过了 2/3 测试,但我似乎无法弄清楚为什么它不能正确计算最后一个测试。
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
if (l.length == 0) return 0
val evens = l.filter(_%2==0)
val odds = l.filter(_%2==1)
val evenSum = evens.foldLeft(0)(_+_)
val oddSum = odds.foldLeft(0)(_+_)
evenSum-oddSum
}
//BEGIN TESTS
val i1 = sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) //answer: -9
val i2 = sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) //answer: 18
val i3 = sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) //answer -133
我的代码输出如下:
defined function sumOfEvenMinusOdd
i1: Int = -9
i2: Int = 18
i3: Int = -200
我非常困惑为什么这些负数会影响我的其余代码。我看到 post 解释了 foldLeft foldRight 的操作顺序,但即使更改为 foldRight 仍然会产生 i3: Int = -200。有没有我遗漏的细节?任何指导/帮助将不胜感激。
问题不在于 foldLeft
或 foldRight
,问题在于您过滤奇数值的方式:
val odds = l.filter(_ % 2 == 1)
应该是:
val odds = l.filter(_ % 2 != 0)
谓词 _ % 2 == 1
只会对正元素产生 true。例如,表达式 -15 % 2
等于 -1
,而不是 1
。
作为旁注,我们还可以提高效率:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
val (evenSum, oddSum) = l.foldLeft((0, 0)) {
case ((even, odd), element) =>
if (element % 2 == 0) (even + element, odd) else (even, odd + element)
}
evenSum - oddSum
}
或者仅通过累积差值更好:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
l.foldLeft(0) {
case (diff, element) =>
diff + element * (if (element % 2 == 0) 1 else -1)
}
}
问题出在您在列表上应用以查找奇数的过滤条件上。
您不适用于负奇数的奇怪情况,因为 mod 2 return -1 对于这种数字。
number % 2 == 0 if number is even
number % 2 != 0 if number is odd
因此,如果您更改过滤条件,一切都会按预期进行。
另一个建议:
既然可以直接使用sum函数,为什么还要用foldleft函数做一个简单的sum运算呢?
test("Test sum Of even minus odd") {
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
val evensSum = l.filter(_%2 == 0).sum
val oddsSum = l.filter(_%2 != 0).sum
evensSum-oddsSum
}
assert(sumOfEvenMinusOdd(List.empty[Int]) == 0)
assert(sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) == -9) //answer: -9
assert(sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) == 18) //answer: 18
assert(sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) == -133)
}
使用此解决方案,您的功能更加清晰,您可以删除功能上的 if
我正在编写一个 Scala 函数,它 returns 列表中偶数元素的总和减去列表中奇数元素的总和。我不能为我的解决方案使用可变、递归或 for/while 循环。下面的代码通过了 2/3 测试,但我似乎无法弄清楚为什么它不能正确计算最后一个测试。
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
if (l.length == 0) return 0
val evens = l.filter(_%2==0)
val odds = l.filter(_%2==1)
val evenSum = evens.foldLeft(0)(_+_)
val oddSum = odds.foldLeft(0)(_+_)
evenSum-oddSum
}
//BEGIN TESTS
val i1 = sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) //answer: -9
val i2 = sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) //answer: 18
val i3 = sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) //answer -133
我的代码输出如下:
defined function sumOfEvenMinusOdd
i1: Int = -9
i2: Int = 18
i3: Int = -200
我非常困惑为什么这些负数会影响我的其余代码。我看到 post 解释了 foldLeft foldRight 的操作顺序,但即使更改为 foldRight 仍然会产生 i3: Int = -200。有没有我遗漏的细节?任何指导/帮助将不胜感激。
问题不在于 foldLeft
或 foldRight
,问题在于您过滤奇数值的方式:
val odds = l.filter(_ % 2 == 1)
应该是:
val odds = l.filter(_ % 2 != 0)
谓词 _ % 2 == 1
只会对正元素产生 true。例如,表达式 -15 % 2
等于 -1
,而不是 1
。
作为旁注,我们还可以提高效率:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
val (evenSum, oddSum) = l.foldLeft((0, 0)) {
case ((even, odd), element) =>
if (element % 2 == 0) (even + element, odd) else (even, odd + element)
}
evenSum - oddSum
}
或者仅通过累积差值更好:
def sumOfEvenMinusOdd(l: List[Int]): Int = {
l.foldLeft(0) {
case (diff, element) =>
diff + element * (if (element % 2 == 0) 1 else -1)
}
}
问题出在您在列表上应用以查找奇数的过滤条件上。 您不适用于负奇数的奇怪情况,因为 mod 2 return -1 对于这种数字。
number % 2 == 0 if number is even
number % 2 != 0 if number is odd
因此,如果您更改过滤条件,一切都会按预期进行。
另一个建议: 既然可以直接使用sum函数,为什么还要用foldleft函数做一个简单的sum运算呢?
test("Test sum Of even minus odd") {
def sumOfEvenMinusOdd(l: List[Int]) : Int = {
val evensSum = l.filter(_%2 == 0).sum
val oddsSum = l.filter(_%2 != 0).sum
evensSum-oddsSum
}
assert(sumOfEvenMinusOdd(List.empty[Int]) == 0)
assert(sumOfEvenMinusOdd(List(1,3,5,4,5,2,1,0)) == -9) //answer: -9
assert(sumOfEvenMinusOdd(List(2,4,5,6,7,8,10)) == 18) //answer: 18
assert(sumOfEvenMinusOdd(List(109, 19, 12, 1, -5, -120, -15, 30,-33,-13, 12, 19, 3, 18, 1, -1)) == -133)
}
使用此解决方案,您的功能更加清晰,您可以删除功能上的 if