3

对返回多个值的 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)

任何想法将不胜感激。谢谢!

4

2 回答 2

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))

但是你最终会得到 IndexedSeqs,而不是 Arrays。

于 2012-12-05T14:28:46.400 回答
1

好吧,如果您愿意,您当然可以编写一个vectorized函数,尽管您需要为每个输入和输出参数设置一个不同的函数。这是用于两进两出的 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)
}
于 2012-12-05T14:29:58.670 回答