使用下面的代码我试图将Double值相加
val v: List[(String, Array[((String, String), Double)])] = List( ("a" , Array((("a" , "b") , 1.0) , (("a" , "c") , 2.0) , (("a" , "d") , 3.0) , (("b" , "c") , 1.0) , (("b" , "d") , 4.0) , (("c" , "d") , 3.0))) )
def sum(xs: Array[((String, String), Double)]): Double = {
@scala.annotation.tailrec
def inner( xs:Array[((String, String), Double)] , accum: Double) : Double = {
xs match {
case x :: tail => inner(tail, accum + x._2)
case Nil => accum
}
}
inner(xs, 0)
}
但错误:
Multiple markers at this line - constructor cannot be instantiated to expected type; found :
scala.collection.immutable.::[B] required: Array[((String, String), Double)] - not found: value tail - constructor
cannot be instantiated to expected type; found : scala.collection.immutable.::[B] required: Array[((String, String),
Double)] - not found: value x
被抛出。
我的逻辑不正确吗?
答案 0 :(得分:2)
::
和Nil
是列表构造函数,因此您无法使用它们来匹配数组。可以在Arrays上匹配,尽管在这种情况下效率非常低,因为你需要在递归调用之间继续构造中间数组:
def sum(xs: Array[((String, String), Double)]): Double = {
@scala.annotation.tailrec
def inner( xs:Array[((String, String), Double)], accum: Double) : Double = {
xs match {
case Array(x, tail@_*) => inner(tail.toArray, accum + x._2)
case Array() => accum
}
}
inner(xs, 0)
}
请注意一个更简单的解决方案:
v.flatMap(_._2.map(_._2)).sum
您可以使用视图来阻止创建不必要的中间集合:
v.view.flatMap(_._2.view.map(_._2)).sum
答案 1 :(得分:0)
不是将Array转换为List并使用递归模式匹配,而是使用这种迭代方法:
val v: List[(String, Array[((String, String), Double)])] = List( ("a" , Array((("a" , "b") , 1.0) , (("a" , "c") , 2.0) , (("a" , "d") , 3.0) , (("b" , "c") , 1.0) , (("b" , "d") , 4.0) , (("c" , "d") , 3.0))) )
//> v : List[(String, Array[((String, String), Double)])] = List((a,Array(((a,b
//| ),1.0), ((a,c),2.0), ((a,d),3.0), ((b,c),1.0), ((b,d),4.0), ((c,d),3.0))))
def sum(xs: Array[((String, String), Double)]): Double = {
var sum = 0.0
for(x <- xs){
sum = sum + x._2
}
sum
} //> sum: (xs: Array[((String, String), Double)])Double
sum(v(0)._2)