对返回多个值的scala函数进行矢量化的最优雅方法是什么?
例如,假设我有以下功能:
def Foobar(foo: Int, bar: Int): (Int, Int) = (foo, bar)
如果它返回一个值,我会做这样的事情:
val a = Array(1, 2, 3)
val b = Array(4, 5, 6)
val c = (a,b).zipped.map(foobar)
但是因为它返回一个元组,我最终得到Array[(Int,Int)]
,而我更喜欢(Array[Int], Array[Int])
。做这样的事情的正确方法是什么?是否有任何聪明的模式可以将其概括为:
val c = vectorized(foobar,a,b)
任何想法都会非常感激。谢谢!
答案 0 :(得分:5)
你可以解压缩它(显然,它与zip相反的操作):
val c = foobar(a,b).unzip
//res2: (s.c.m.IndexedSeq[Int], s.c.m.IndexedSeq[Int]) = (ArrayBuffer(1, 2, 3),ArrayBuffer(4, 5, 6))
但你最终会使用IndexedSeq,而不是Arrays。
答案 1 :(得分:1)
嗯,如果你愿意的话,你当然可以写一个vectorized
函数,尽管你需要为每个输入和输出arity提供一个不同的函数。这是2.10版本(2.9将使用Manifest
而不是ClassTag
)两个输入和两个输出:
import reflect.ClassTag
def vectorized[A, B, C: ClassTag, D: ClassTag](
f: (A,B) => (C,D), a: Array[A], b: Array[B]
): (Array[C], Array[D]) = {
val c = Array.newBuilder[C]
val d = Array.newBuilder[D]
for (i <- 0 until math.min(a.length, b.length)) {
val x = f(a(i), b(i))
c += x._1
d += x._2
}
(c.result, d.result)
}