2011-01-10 9 views
1

私はScalaの多次元コレクションを扱うためのエレガントな方法を探しています。私の理解では、私は、次の2次元配列の場合のように、集計使用して5次元のコレクションまで持つことができるということです。コレクションの寸法と効率的でエレガントな方法でコレクションをトラバースする方法

val test = Array.tabulate[Double](row,col)(_+_) 

と私が使用して配列の要素にアクセスできることを

for(i<-0 until row) { 
     for(j<-0 until col) { 
     test(i)(j) = 0.0 
     } 
    } 

私は私のような何かをせずに、コレクションの構造を決定し、それにまたがるの簡潔な方法であるかもしれないものを、ハンドリングするつもりだ何先験的がわからない場合:

case(Array(x)) => 
     for(i<-1 until dim1) { 
      test(i) = 0.0 
     } 

    case(Array(x,y)) => 
     for(i<-1 until dim1) { 
      for(j<-1 until dim2) { 
       test(i)(j) = 0.0 
      } 
     } 

    case(Array(x,y,z)) => 
    ... 

寸法値n1、n2、n3などはプライベートですね。また、1つのケースでトラバーサルを処理したい場合は、n次元オブジェクトを扱うときに、1次元ベクトルに2次元配列をアンラップする同じトリックを使用しますか?

事前に感謝

ブルース

答えて

4

私は、この場合にはマッチング再帰とパターンを使用します。

def doSome(a:Array[_]){ 
    for(i <- a){ 
     i match{ 
     case x:Array[_] => doSome(x) 
     case x => println(x) // do something sensible here 
     } 
    } 
}

1

まず、いくつかの修正:

val test = Array.tabulate[Double](row,col)(_+_) 

これはArray[Array[Double]]が生成されます、すべての要素をゼロにする最も簡単な方法は次のとおりです。

test foreach { inner => in.indices foreach { _ => 0.0 } } 

外部配列に含まれる各内部配列をループし、内部配列に対して各要素を更新します。そこ要素の実際の数を知る必要がありますしない、またそれがそうすることが望ましい

それは、がはるかに簡単mapを使用することです(ただ並列アレイで!ということを想像)、および配列などと連携しかし、それはあなたの元の要求の精神に逆らっているように見えるので、素早く動いているようです。

また、表関数から返された多次元配列の性質を誤解しています配列の)。パターンマッチングもJava switch文のように使用していますが、これは正しくありません。様々な次元の配列を一致させるために、あなたはこのような何かしたいと思います:

case Array[Double] => ... 
case Array[Array[Double]] => ... 

をしかし、私はそのアプローチに対して助言するだろう。型システムで安全に表現するのは簡単ではなく、与えられた引数の数に基づいてどの型が返されたのかはすでに分かっています

+0

ありがとう、これは私の理解に役立ちます。 –

+0

私はあなたの考えが「地図を使うのがはるかに簡単で、不変だったかのように配列を使って作業する方が簡単ですが、元の要求の精神に反しているように思えます。に..."。 –

+1

@ Bruce - 慣用的なScalaでは、通常、コレクション全体を変換する方法があります。ですから、何らかの形の多次元コレクションから始まり、(mapのような)操作を適用して、元のまま変更されたコレクションになります。すべてが不変なので、これは実際にはかなり効率的です。このような構造のセルを1つだけ変更すると、新しいフォームのすべての行(変更がある行を除く)が元の行への参照になります。これは変更できないという保証があるため可能です。 –

関連する問題