0

次の Matlab 論理インデックス パターンを Scala コードに変換しようとしています。

% x is an [Nx1] array of Int32
% y is an [Nx1] array of Int32
% myExpensiveFunction() processes batches of unique x.

ux = unique(x);
z = nan(size(x));
for i = 1:length(ux)
  idx = x == ux(i);
  z(idx) = myExpensiveFuntion(x(idx), y(idx));
end

val x: Array[Int]Scalaで作業していると仮定します。これを行う最善の方法は何ですか?

編集:明確にするために、一意のxでグループ化された(x、y)のバッチを一度に処理し、初期入力に対応する順序で結果(z)を返すことを検討しています。私は x を並べ替えても構いませんが、最終的には元の並べ替えられていない順序に戻す必要があります。私の主な要件は、すべてのインデックス作成/マッピング/並べ替えを明確かつ合理的に効率的な方法で処理することです。

4

3 に答える 3

1

これのほとんどは、Scala では非常に単純です。普通とは少し違うのは、一意のxインデックスだけです。Scala では、「groupBy」を使用してそれを行います。これは非常にインデックスを多用する方法であるため、あきらめてインデックスを使用することにします。

val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
  is.foreach(i => z(i) = myExpensiveFunction(xi, y(i)))
}
z

に向かうベクトルがなくても生きていけると仮定しますmyExpensiveFunction。そうでない場合は、

val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
  val xs = Array.fill(is.length)(xi)
  val ys = is.map(i => y(i)).toArray
  val zs = myExpensiveFunction(xs, ys)
  is.foreach(i => z(i) = zs(i))
}
z

これは Scala で計算を行う最も自然な方法でも最も効率的な方法でもありませんが、高価な関数が高価な場合は効率を気にする必要はありません。

(matlab アルゴリズムを他のほとんどすべてのものに変換するには、ある程度の苦痛や再考が必要です。これは、matlab の「自然な」計算が他のほとんどの言語の計算とは異なるためです。)

于 2013-02-28T16:28:23.323 に答える
0
scala> def process(xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double): Array[Double] = {
     |   val ux = xs.distinct
     |   val zs = Array.fill(xs.size)(Double.NaN)
     |   for(x <- ux) {
     |     val idx = xs.indices.filter{ i => xs(i) == x }
     |     val res = f(idx.map(xs), idx.map(ys))
     |     idx foreach { i => zs(i) = res }
     |   }
     |   zs
     | }
process: (xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double)Array[Double]

scala> val xs = Array(1,2,1,2,3)
xs: Array[Int] = Array(1, 2, 1, 2, 3)

scala> val ys = Array(1,2,3,4,5)
ys: Array[Int] = Array(1, 2, 3, 4, 5)

scala> val f = (a: Seq[Int], b: Seq[Int]) => a.sum/b.sum.toDouble
f: (Seq[Int], Seq[Int]) => Double = <function2>

scala> process(xs, ys, f)
res0: Array[Double] = Array(0.5, 0.6666666666666666, 0.5, 0.6666666666666666, 0.6)
于 2013-02-28T17:11:56.003 に答える
0

重要な点は、Matlab をunique正しく理解することです。簡単な解決策は、 a を使用しSetて一意の値を決定することです。

val occurringValues = x.toSet

occurringValues.foreach{ value =>
  val indices = x.indices.filter(i => x(i) == value)
  for (i <- indices) {
    z(i) = myExpensiveFunction(x(i), y(i))
  }
}

myExpensiveFunction注:要素単位の操作に変更することは可能だと思います...

于 2013-02-28T16:31:23.653 に答える