【问题标题】:scala sum list of numeric valuesscala sum 数值列表
【发布时间】:2018-03-25 22:20:01
【问题描述】:

我想要一个通用函数来对列表中的值求和。

以下代码无法编译:

def sum[T : Numeric](x: List[T]): T = {
    if(x.isEmpty) 0
    else x.head + sum(x.tail)

  }

编译错误是:

error: type mismatch;

[INFO]  found   : Int(0) 

[INFO]  required: T

[INFO]     if(x.isEmpty) 0

【问题讨论】:

  • 为什么不直接使用x.sum(其中xList[T]T 定义了一个隐含的Numeric[T] 实例)?
  • 我在网上遇到了代码片段,很好奇如何使它更通用。这是一个理解 scala 的练习(我不在学校,只是好奇)
  • 顺便说一句,使用这种类型的函数需要注意一件事:它不是 尾递归。如果你有一个很长的列表,你会得到一个堆栈溢出。 (现在我以前在哪里听过这个表达式?)对于尾递归函数,递归调用必须是最后一个表达式。
  • @MIke Allen,感谢您的提醒

标签: scala


【解决方案1】:

这个错误告诉你你已经指定了返回类型是T,但是你总是为一个空列表返回一个0,它是一个Int。如果传入的列表包含其他内容,即 TDouble 或某些自定义类型怎么办?试试这个:

if(x.isEmpty) implicitly[Numeric[T]].zero

完整的工作方法:

def sum[T : Numeric](x: List[T]): T = {
  if (x.isEmpty) implicitly[Numeric[T]].zero
  else implicitly[Numeric[T]].plus(x.head, sum(x.tail))
}

或者:

def sum[T](x: List[T])(implicit num: Numeric[T]): T = {
  import num._
  if (x.isEmpty) zero
  else x.head + sum(x.tail)
}

【讨论】:

  • 你也错过了implicitly[Numeric[T]].plus! ;)
  • 是的,否则:错误:类型不匹配; [INFO] 找到 : List[T] [INFO] required: List[String] [INFO] else x.head + sum(x.tail)
  • 除了现在我得到“无法'隐式'解析符号”
  • 太棒了。太感谢了。真的很感激
  • 正确,你必须确保使用数字的加法。我已经编辑以包含对我有用的完整示例:)
【解决方案2】:

试试这个:

def sum[T](x: List[T])(implicit num: Numeric[T]): T = x.foldLeft(num.zero)(num.plus)

【讨论】:

    【解决方案3】:

    使用reduce(如果您不想为sum设置初始值)否则使用fold操作:

    def sumWithReduce[T](lst: List[T])(implicit numericType: Numeric[T]):T 
    = lst.reduce(numericType.plus)
    
    def sumWithFold[T](lst: List[T])(implicit numericType: Numeric[T]):T 
    = lst.fold(numericType.zero)(numericType.plus)
    

    【讨论】:

    • reduce 对空列表失败,fold 更健壮。
    猜你喜欢
    • 2012-04-17
    • 1970-01-01
    • 2021-06-02
    • 2023-04-01
    • 1970-01-01
    • 2016-09-22
    • 1970-01-01
    • 2021-05-22
    • 2023-02-05
    相关资源
    最近更新 更多