【问题标题】:Scala Type Mismatch in FoldLeft operationFoldLeft 操作中的 Scala 类型不匹配
【发布时间】:2019-02-01 03:11:57
【问题描述】:

我对 Scala 很陌生,所以请原谅这可能是对语言的简单误解。我有一个功能:

def compareNextElemToMinElem(lst: List[Int]) = {
    val max = lst.foldLeft((lst(0),lst(0),0)) { (minSoFar:Int, x:Int, maxDiff:Int) => 
        if (x < minSoFar) (minSoFar, x, maxDiff) 
        if (x - minSoFar > maxDiff) (minSoFar, x, x - minSoFar)
        else (minSoFar, x, x - minSoFar)
    }
    max._3
}

基本上它应该一次去一个元素,并跟踪迄今为止最大的元素差异。通过调用 max._3,我希望从 foldLeft 调用中返回最终的 maxDiff。我收到一个错误:

type mismatch;
 found   : (Int, Int, Int) => (Int, Int, Int)
 required: ((Int, Int, Int), Int) => (Int, Int, Int)
    val max = lst.foldLeft((lst(0),lst(0),0)) { (minSoFar:Int, x:Int, maxDiff:Int) => 

此外,我必须使用 (minSoFar:Int, x:Int, maxDiff:Int) 而不是 (minSoFar, x, maxDiff) 以避免出现 missing parameter type 错误。这是为什么呢?

【问题讨论】:

  • “元素的最大区别” - 在 what 元素中?它应该计算什么? lst.max - lst.min?或者两个连续元素之间的最大差异?在任何情况下,折叠都不需要三参数函数,您必须以不同的方式嵌套元组,并且您可能需要一个 case 来正确匹配所有组件。
  • 不是lst.max - lst.min,而是当前元素减去到目前为止的最小值。我不确定你的意思,我对此很陌生。
  • for list(1,2,3,-1,4,-2) 我想要 4-(-1) 或 5。

标签: scala fold


【解决方案1】:

语法和逻辑似乎都不完全正确,这里有一个可能的解决方法:

def compareNextElemToMinElem(lst: List[Int]) = {
  lst.foldLeft((lst.head, lst.head)) { case ((minSoFar, maxDiff), x) =>
    if (x < minSoFar) (x, maxDiff) 
    else if (x - minSoFar > maxDiff) (minSoFar, x - minSoFar)
    else (minSoFar, maxDiff)
  }._2
}

println(compareNextElemToMinElem(List(1,-2,3,-1,4,8,2)))

打印

10

这是8 - (-2)

简要说明:

  1. 您想要跟踪两个值:minSoFarmaxDiff,而不是三个。
  2. 你要查看列表的内容:x必须来自列表, 不是来自上一步传递的“累加器”
  3. fold,一般来说,接受一个接受两个参数的函数:

    list.fold(accumulator0){ (acc, currentValue) => nextAcc }
    
  4. 因为这里你的累加器acc 本身就是一个元组,所以你必须在第一个组件上与case 进行模式匹配,所以:

    list.fold((a0, b0)) { case ((ai, bi), x) => (nextAi, nextBi) }
    
  5. 我不明白你的 if-else 逻辑,不能保证它会达到你的预期。

【讨论】:

  • 明白这是有道理的。如果我们不在匹配语句中,为什么我们需要case ((minSoFar, maxDiff), x)
  • @FranklinHarvey 正如我所说,它用于将acc 元组分解为(minSoFar, maxDiff)。搜索“scala pattern matching case functions”(搜索更好的链接)。
【解决方案2】:

你必须将 minSofar 和 maxDiff 作为 Tuple2 或 pair.So 它应该像下面的代码:

def compareNextElemToMinElem(lst: List[Int]) = {
    val max = lst.foldLeft((lst(0),0)) { (p : Tuple2[Int,Int], x:Int) =>
      var minSoFar = p._1;
      var maxDiff = p._2
      if (x < minSoFar) {
        maxDiff = maxDiff + minSoFar - x
        minSoFar = x
      }
      if (x - minSoFar > maxDiff){
        maxDiff = x - minSoFar
      }
      (minSoFar,maxDiff)
    }
    max._2
  } 

关注link 以了解有关 foldleft 参数的更多信息。

【讨论】:

  • 它到底是做什么的?由于奇怪的maxDiff + x - minSoFar,我认为它会在给定的示例上输出6,但更令人惊讶的是,compareNextElemToMinElem(List(1,2,3,-1,4,-2)) 给出的是4而不是5
  • 应该是 maxDiff = maxDiff - ( x - minSoFar)
猜你喜欢
  • 1970-01-01
  • 2019-12-14
  • 2012-08-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多