2016-03-30 12 views
2

における最大値は私はこのような例えば2次元アレイを有すると仮定する。検索「列方向」は、2次元アレイ

私はマトリックス状に上記の配列を記述する場合、それは私が「列方向」最大で何を意味するかは明らかだ:

4 0 0 0 
3 
3 4 40 1 
50 2 
---------- 
50 4 40 1 (result) 

ので、この場合の答えはArray(50,4,40,1)だろう(空の値は無視されるだろう)。

私はこのようにそれを行うことができます。

A1.foldLeft(A1.head)((x1, x2) => 
    x1.padTo(x2.length, Int.MinValue).zip(x2.padTo(x1.length,Int.MinValue)). 
    map { pair => pair._1 max pair._2 } 
) 

何とかこれは、このような単純なもののために非常にハードコアを感じています。だから私はこれを行う簡単な方法に感謝します。

はたぶん

1)直接これを行うにはいくつかの機能がありますか?

2)「デフォルト値で圧縮する」いくつかの方法:x1.padTo(x2.length, Int.MinValue).zip(x2.padTo(x1.length,Int.MinValue))

3)これを改善する他の方法はありますか?

答えて

6

使用.tranposeあなたArray[Array[Int]]の「列」を取得するために、それらの全ての最大値を取得するために.map(_.max)を呼び出します。

scala> val A1 = Array(Array(4,0,0,0),Array(3),Array(3,4,40,1),Array(50,2)) 
A1: Array[Array[Int]] = Array(Array(4, 0, 0, 0), Array(3), Array(3, 4, 40, 1), Array(50, 2)) 

scala> A1.transpose 
res5: Array[Array[Int]] = Array(Array(4, 3, 3, 50), Array(0, 4, 2), Array(0, 40), Array(0, 1)) 

scala> A1.transpose.map(_.max) 
res6: Array[Int] = Array(50, 4, 40, 1) 

編集.tranposeしている場合に例外をスローすることがあります後でArray[Array[T]]に遭遇するArrayは、第1のものよりも長い:

scala> Array(Array(1,2,3), Array(1,2,3,4)).transpose 
java.lang.ArrayIndexOutOfBoundsException: 3 
    at scala.collection.mutable.ArrayOps$$anonfun$transpose$1$$anonfun$apply$1.apply(ArrayOps.scala:102) 
    at scala.collection.mutable.ArrayOps$$anonfun$transpose$1$$anonfun$apply$1.apply(ArrayOps.scala:101) 
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) 
    at scala.collection.mutable.ArrayOps$ofInt.foreach(ArrayOps.scala:234) 
    at scala.collection.mutable.ArrayOps$$anonfun$transpose$1.apply(ArrayOps.scala:101) 
    at scala.collection.mutable.ArrayOps$$anonfun$transpose$1.apply(ArrayOps.scala:99) 
    at scala.collection.IndexedSeqOptimized$class.foreach(IndexedSeqOptimized.scala:33) 
    at scala.collection.mutable.ArrayOps$ofRef.foreach(ArrayOps.scala:186) 
    at scala.collection.mutable.ArrayOps$class.transpose(ArrayOps.scala:99) 
    at scala.collection.mutable.ArrayOps$ofRef.transpose(ArrayOps.scala:186) 
    ... 32 elided 

scala> Array(Array(1,2,3,4), Array(1,2,3)).transpose 
res5: Array[Array[Int]] = Array(Array(1, 1), Array(2, 2), Array(3, 3), Array(4)) 

それはあなたのケースで起こることができる場合は、常に(降順)内側の配列の長さによって、外側の配列を並べ替えることができます:

scala> Array(Array(1,2,3), Array(1,2,3,4)).sortBy(-_.length).transpose 
res6: Array[Array[Int]] = Array(Array(1, 1), Array(2, 2), Array(3, 3), Array(4)) 
+0

ニース。私はこのような単純なことは分かっていたが、それを理解することはできなかった。しかし、最初に並べ替えることは少し残念です。私はジョバンニの答えがかなり速くなると思う... – Pekka

3

transpose答えが正解です。完全を期すために、zipAll関数が存在します。倍+ジップバージョンは次のようになります。最大は可換モノイドであり、あなたはあなたがたreduce(左または右ではない)

A1.par.reduce((x1, x2) => 
    x1.zipAll(x2, Int.MinValue, Int.MinValue) 
    .map { case (x, y) => x max y } 
) 

を使用することができますので、

A1.reduceLeft((x1, x2) => 
    x1.zipAll(x2, Int.MinValue, Int.MinValue) 
    .map { case (x, y) => x max y } 
) 

を簡単にパラレルバージョンを書くことができます適切なトラックでは、このバージョンは間違いなく高速であり、ソート+大容量配列の転置よりはるかに少ないメモリを使用します。

val A1 = Array.fill(100000)(Array.fill(Random.nextInt(100000))(Random.nextInt())) 

あなたはメモリにのみ、あなたが(移調、その後、すなわちソート)中間結果を保存したくないmaxを計算する必要がある場合は、あなたの考えは、間違いなく行く方法です。行列がディスク上にある場合は、ロードする必要はありません。行の上を1回だけ反復することができます。

+0

@Pekka私はいくつかの発言を追加した、あなたのアイデアは間違いなく正しいものでした。アルゴリズム的には –

+1

と言いますまた、私はあなたのソリューションを "ハードコア"とは考えません。折りたたみとマッピングがわかると、機能プログラミングの基礎を知っている人にすぐに分かります。 –

+1

もう一度@Giovanniに感謝します!あなたの答えを本当に感謝します。私はこのような無邪気な行からかなり多くを学びました。>) – Pekka