7

私はこのようなScalaコードを持っています

var i = 1
for(e <- array) {
    acc += e * i
    i += 1
}

配列の最初の要素に1を掛け、次の要素に2を掛け、次の要素に3を掛けて、すべてをアキュムレータに追加する必要があります。Scalaでこれを行うには、おそらく折りたたむことでさえ、より良い方法があると思いますか?

4

4 に答える 4

15

「より良い」はあなたの目標が何であるかに依存します。短くて明確ですか?おそらく

{ for (i <- array.indices; e = array(i)) yield (i+1)*e }.sum

また

array.indices.map(i => (i+1)*array(i)).sum

(または、途中で中間体を作成するため、少し速くなります。

array.indices.iterator.map(i => (i+1)*array(i)).sum

)。

通常、短く明確にする必要があります。

速い?次に、古い学校に行く必要があります:

var i = 0
var acc = 0
while (i < array.length) {
  acc += (i+1)*array(i)
  i += 1
}

または再帰を使用します

def sum(a: Array[Int], i: Int = 0, acc: Int = 0): Int =
  if (i >= a.length) acc else sum(a, i+1, (i+1)*a(i) + acc)
sum(array)
于 2013-03-05T16:01:41.837 に答える
10

私は読みやすいzipWithIndexを好みます:

array.zipWithIndex.map { case (e, i) => e * (i + 1) }.sum
于 2013-03-05T15:31:33.253 に答える
5
val x = List(1,1,1,1,1,1)
(((0,1) /: x){case ((acc, mult), l) => (acc + (l * mult), mult + 1) })._1

つまり、アキュムレータ0と乗数1から始めて、リストの各要素を折りたたんで、アキュムレータを1に変更しacc + (l * mult)、乗数を1ずつ増やします。最後に最後の乗数も取得するので、次のように呼び出します。._1アキュムレータを取得するだけです。

編集:@RexKerrが以下の彼の回答(およびコメント)で指摘しているように、パフォーマンスが主要な懸念事項である場合は、明示的な再帰的方法を使用することをお勧めします。

于 2013-03-05T15:27:12.293 に答える
2

私が提案することがより機能的であるため、それを行うためのより良い方法であるかどうかはわかりません(==パフォーマンスが遅くなります):

(0 /: (array zipWithIndex)) {(a, i) => (i._1 * (i._2 + 1)) + a}

これは、 http: //www.scala-lang.org/api/current/index.html#scala.ArrayのzipWithIndexメソッドによって生成された配列に対してfoldLeftを実行します。

zipWithIndexは、コレクションの要素とそのインデックスを単純に圧縮します。

于 2013-03-05T15:36:24.503 に答える