我的目标是创建一个列表,其中包含来自其他两个列表的相应元素的平均值。例如,给定列表
val a = List[Double](1, 2)
val b = List[Double](3, 4)
我想创建列表(2, 3)
。我的麻烦并不是我找不到有效的策略,而是我找到了太多的策略,无法确定哪一个是最佳实践。这是我到目前为止所发现的。
// Strategy 1
a.zip(b).map(pair => (pair._1 + pair._2) / 2)
// Strategy 2
a.zip(b).map { case (an, bn) => (an + bn) / 2 }
// Strategy 3
(a, b).zipped.map((an, bn) => (an + bn) / 2)
// Strategy 4
(a, b).zipped.map(_ / 2 + _ / 2)
策略4对我来说似乎最干净,但它让我感到紧张,因为
(a, b).zipped.map((_ + _) / 2)
似乎非常相似,但却给出错误
error: missing parameter type for expanded function ((x$1, x$2) => x$1.$plus(x$2))
我真的不明白。
我理解人们可能不同意哪种解决方案最干净,但我是Scala的新手,我正在努力建立产生可读代码的良好习惯。
总结一下:您认为哪种策略最干净(可能包括我未提出的策略),为什么最后一个示例会出错?
答案 0 :(得分:3)
正如你所看到的,这些是非常相似的方法,所以最终它是一个品味问题。请注意,变体1和2基本相同,变体2只使用模式匹配来将元组分开。
所以基本上你有(a zip b).map
对(a, b).zipped.map
。现在您发现zipped
变体更“干净”。从技术上讲,这会产生Tuple2Zipped
,我个人认为应该不鼓励采用这种方法。虽然它允许您从一些更简单的语法中受益,即map
使用Function2
而不是Function1[Tuple2[...]]
,但此类型完全在常规Scala集合类型层次结构之外,因此更快或者稍后,当您尝试使用Tuple2Zipped
做一些非平凡的事情时,您会遇到很多不一致。
因此,我强烈推荐使用中缀运算符编写更加对称的变量2:
(a zip b).map { case (an, bn) => (an + bn) / 2 }