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

しかし、配列ではなく、IndexedSeq になってしまいます。

于 2012-12-05T14:28:46.400 に答える
1

もちろん、vectorized必要に応じて関数を作成することもできますが、入力アリティと出力アリティごとに異なる関数が必要になります。これは 2.10 バージョンです (2.9Manifestでは の代わりに使用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 に答える