Scala:foldLeft的问题,列表中有负数

Meg*_*ers 1 scala filter pattern-matching fold

我正在编写一个Scala函数,它返回列表中偶数元素的总和,减去列表中奇数元素的总和.我不能为我的解决方案使用mutable,递归或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
Run Code Online (Sandbox Code Playgroud)

我的代码正在输出:

defined function sumOfEvenMinusOdd
i1: Int = -9
i2: Int = 18
i3: Int = -200
Run Code Online (Sandbox Code Playgroud)

我非常困惑为什么这些负数会使我的其余代码绊倒.我看到一篇文章解释了foldLeft foldRight的操作顺序,但即使改为foldRight仍然会产生i3:Int = -200.有没有我遗漏的细节?任何指导/帮助将不胜感激.

Yuv*_*kov 7

问题不是foldLeft或者foldRight,问题是你过滤掉奇数值的方式:

val odds = l.filter(_ % 2 == 1)
Run Code Online (Sandbox Code Playgroud)

应该:

val odds = l.filter(_ % 2 != 0)
Run Code Online (Sandbox Code Playgroud)

谓词_ % 2 == 1只会对正元素产生真实.例如,表达式-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
}
Run Code Online (Sandbox Code Playgroud)

或者仅通过累积差异来更好:

def sumOfEvenMinusOdd(l: List[Int]): Int = {
  l.foldLeft(0) {
    case (diff, element) =>
      diff + element * (if (element % 2 == 0) 1 else -1)
  }
}
Run Code Online (Sandbox Code Playgroud)

  • 你是一个真正的救生员,你不知道我被困在了多久!谢谢! (2认同)
  • 更有效地积累差异而不是在最后做到这一点.你也不需要`isEmpty`测试,即使有一个空列表它也能正常工作. (2认同)