如何获得Scala中两个列表的平方和?

时间:2011-10-25 01:46:09

标签: list scala

如果我有两个列表

val first = List(1, 2, 3)
val second = List(4, 5, 6)

我如何获得以下内容?

(1-4)^2 + (2-5)^2 + (3-6)^2

3 个答案:

答案 0 :(得分:12)

zip,map和sum:

first.view.zip(second).map(t => t._1 - t._2).map(x => x*x).sum
  • zip 将两个列表中的元素组合成一个元组
  • view 用于使列表懒惰地计算,以便不在两个地图调用之间构建结构

(编辑以reduceLeft替换sum


看到评论后,我觉得我必须回来解释一下观点。基本上,视图将Traversable转换为类似迭代器的结构,以便在应用mapzip等方法时不必创建多个中间结构。 GenIteratableViewLike的类型成员可以了解哪些操作有特殊处理。所以通常如果你有一堆map,filter,drop,takeWhile按顺序应用,你可以使用view来获得一些性能。经验法则是提前应用view以最小化创建的中间List的数量,并在必要时使用force在最后返回List(或任何集合)你正在使用)。因此丹尼尔的建议。

关于表现的事情是,在实践中,如果这很重要,你必须做一个现实检查。这里有一些数字(越低越好):

no view List(62, 62, 62, 62, 63) sum: 311
view before zip List(32, 31, 15, 16, 31) sum: 125
view after zip List(31, 46, 46, 31, 31) sum: 185
iterator List(16, 16, 16, 16, 15) sum: 79
zipped List(62, 47, 62, 46, 47) sum: 264

代码在这里:

import testing.Benchmark

def lots[T](n: Int, f: => T): T = if (n > 0) { f; lots(n - 1, f) } else f

def bench(n: Int, id: String)(block: => Unit) {
  val times = (new testing.Benchmark { 
    def run() = lots(10000, block)
  }).runBenchmark(n)
  println(id + " " + times + " sum: " + times.sum)
}

val first = List(1, 2, 3)
val second = List(4, 5, 6)

bench(5, "no view") { first.zip(second).map(t => t._1 - t._2).map(x => x*x).sum }
bench(5, "view before zip") { first.view.zip(second).map(t => t._1 - t._2).map(x => x*x).sum }
bench(5, "view after zip") { first.zip(second).view.map(t => t._1 - t._2).map(x => x*x).sum }
bench(5, "iterator") { first.iterator.zip(second.iterator).map(t => t._1 - t._2).map(x => x*x).sum }
bench(5, "zipped") { (first, second).zipped.map((a,b) => a - b).map(x => x*x).sum }

答案 1 :(得分:5)

一般情况下,您可能希望定义一个函数,如果它是复杂的,而不是应用多个映射。您可以将此作为辅助方法,或匿名内联。

def op(i: Int, j: Int) = { val m = i - j; m * m }

(first, second).zipped.map(op).sum

或者

(first, second).zipped.map( (i, j) => { val m = i - j; m * m } ).sum
在这些情况下,

zippedzip更方便,因为它可以映射到一个带有2个参数的函数,而不是一个必须使用{{1}的单个元组}和._1字段。

答案 2 :(得分:2)

左折:

(0 /: first.zip (second)) ((a, b) => a + (b._1 - b._2)*(b._1 - b._2))

从拉链开始。