2

次のマトリックスがあるとしましょう:


val grid = Array(
  Array( 1, 2, 3,  4, 5, 6,  7, 8, 9), 
  Array(11,12,13, 14,15,16, 17,18,19), 
  Array(21,22,23, 24,25,26, 27,28,29), 

  Array(31,32,33, 34,35,36, 37,38,39), 
  Array(41,42,43, 44,45,46, 47,48,49), 
  Array(51,52,53, 54,55,56, 57,58,59), 

  Array(61,62,63, 64,65,66, 67,68,69), 
  Array(71,72,73, 74,75,76, 77,78,79), 
  Array(81,82,83, 84,85,86, 87,88,89)
)

どうすれば、できれば関数的な方法で、この行列を変換できますか:


val gridWithFields = Array(
  Array(1,2,3, 11,12,13, 21,22,23),
  Array(4,5,6, 14,15,16, 21,22,23),
  Array(7,8,9, 17,18,19, 27,28,29),
  ... 
)

*更新*
いくつかのベンチマークを行いましたが、メモリの結果が正しいかどうかはわかりません。いずれにせよ、それらは次のとおりです。

@maxmc for のソリューション

alg1 のサイクル: 10 時間: 2712683ns メモリ: 459572
alg1 サイクル: 100 時間: 914297ns メモリ: 458191
alg1 のサイクル: 1000 時間: 85102ns メモリ: 457944
alg1 のサイクル: 10000 時間: 68742ns メモリ: 457943

@Daniel C. Sobralソリューション

alg2 サイクル: 10 時間: 3747031ns メモリ: 458889
alg2 サイクル: 100 時間: 1796564ns メモリ: 457951
alg2 サイクル: 1000 時間: 186215ns メモリ: 457220
alg2 のサイクル: 10000 時間: 122642ns メモリ: 456708

@またはペレス解

alg3 サイクル: 10 時間: 741475ns メモリ: 457472
alg3 サイクル: 100 時間: 542181ns メモリ: 457914
alg3 サイクル: 1000 時間: 248020ns メモリ: 457911
alg3 サイクル: 10000 時間: 119105ns メモリ: 457919

@Hbf ソリューション

alg4 サイクル: 10 時間: 179093ns メモリ: 457472
alg4 のサイクル: 100 時間: 121072ns メモリ: 457069
alg4 サイクル: 1000 時間: 78123ns メモリ: 456719
alg4 サイクル: 10000 時間: 75948ns メモリ: 455913

@Eastsunソリューション

alg5 サイクル: 10 時間: 144037ns メモリ: 457512
alg5 サイクル: 100 時間: 40672ns メモリ: 457059
alg5 サイクル: 1000 時間: 42236ns メモリ: 456119
alg5 のサイクル: 10000 時間: 46480ns メモリ: 455952

MacMini(2012)でテストしました。メモリの結果は本当に奇妙なので、ソースはここにあります。悪い間違いやアンチパターンがある場合は教えてください =) https://github.com/Stimphonier/MatrixBench

4

7 に答える 7

4

「for」アプローチ:

for(x <- 0 until 9 by 3) yield
  (for {
    row <- 0 until 9;
    col <- x until x + 3 by 3;
    i <- col until col + 3
  } yield grid(row)(i)).toArray   
于 2013-02-26T14:43:50.017 に答える
4

グループ化して転置します。正しい順序を見つけた REPL セッションを示します。

まず、データにはグループ化があります。これはスペースで明確に示されています。3 行ごと、各行内では 3 要素ごと。したがって、最初に行うことは、グループ化を明示的にすることです。

scala> grid.map(row => (row grouped 3).toArray)
res7: Array[Array[Array[Int]]] = Array(Array(Array(1, 2, 3), Array(4, 5,
 6), Array(7, 8, 9)), Array(Array(11, 12, 13), Array(14, 15, 16), Array(
17, 18, 19)), Array(Array(21, 22, 23), Array(24, 25, 26), Array(27, 28,
29)), Array(Array(31, 32, 33), Array(34, 35, 36), Array(37, 38, 39)), Ar
ray(Array(41, 42, 43), Array(44, 45, 46), Array(47, 48, 49)), Array(Arra
y(51, 52, 53), Array(54, 55, 56), Array(57, 58, 59)), Array(Array(61, 62
, 63), Array(64, 65, 66), Array(67, 68, 69)), Array(Array(71, 72, 73), A
rray(74, 75, 76), Array(77, 78, 79)), Array(Array(81, 82, 83), Array(84,
 85, 86), Array(87, 88, 89)))

scala> (res7 grouped 3).toArray
res8: Array[Array[Array[Array[Int]]]] = Array(Array(Array(Array(1, 2, 3)
, Array(4, 5, 6), Array(7, 8, 9)), Array(Array(11, 12, 13), Array(14, 15
, 16), Array(17, 18, 19)), Array(Array(21, 22, 23), Array(24, 25, 26), A
rray(27, 28, 29))), Array(Array(Array(31, 32, 33), Array(34, 35, 36), Ar
ray(37, 38, 39)), Array(Array(41, 42, 43), Array(44, 45, 46), Array(47,
48, 49)), Array(Array(51, 52, 53), Array(54, 55, 56), Array(57, 58, 59))
), Array(Array(Array(61, 62, 63), Array(64, 65, 66), Array(67, 68, 69)),
 Array(Array(71, 72, 73), Array(74, 75, 76), Array(77, 78, 79)), Array(A
rray(81, 82, 83), Array(84, 85, 86), Array(87, 88, 89))))

正しいかどうか見てみましょう。

scala> res8(0)
res9: Array[Array[Array[Int]]] = Array(Array(Array(1, 2, 3), Array(4, 5,
 6), Array(7, 8, 9)), Array(Array(11, 12, 13), Array(14, 15, 16), Array(
17, 18, 19)), Array(Array(21, 22, 23), Array(24, 25, 26), Array(27, 28,
29)))

はい、まさに変換したいデータの単位です。試してみましょう:

scala> res9.transpose
res10: Array[Array[Array[Int]]] = Array(Array(Array(1, 2, 3), Array(11,
12, 13), Array(21, 22, 23)), Array(Array(4, 5, 6), Array(14, 15, 16), Ar
ray(24, 25, 26)), Array(Array(7, 8, 9), Array(17, 18, 19), Array(27, 28,
 29)))

望んだ通りに!それでは、マトリックス全体に対してそれを行いましょう:

scala> res8 map (_.transpose)
res11: Array[Array[Array[Array[Int]]]] = Array(Array(Array(Array(1, 2, 3
), Array(11, 12, 13), Array(21, 22, 23)), Array(Array(4, 5, 6), Array(14
, 15, 16), Array(24, 25, 26)), Array(Array(7, 8, 9), Array(17, 18, 19),
Array(27, 28, 29))), Array(Array(Array(31, 32, 33), Array(41, 42, 43), A
rray(51, 52, 53)), Array(Array(34, 35, 36), Array(44, 45, 46), Array(54,
 55, 56)), Array(Array(37, 38, 39), Array(47, 48, 49), Array(57, 58, 59)
)), Array(Array(Array(61, 62, 63), Array(71, 72, 73), Array(81, 82, 83))
, Array(Array(64, 65, 66), Array(74, 75, 76), Array(84, 85, 86)), Array(
Array(67, 68, 69), Array(77, 78, 79), Array(87, 88, 89))))

あとは平らに戻すだけです。グループ化したときと逆の順序でフラット化する必要があります。

scala> res11.flatten
res12: Array[Array[Array[Int]]] = Array(Array(Array(1, 2, 3), Array(11,
12, 13), Array(21, 22, 23)), Array(Array(4, 5, 6), Array(14, 15, 16), Ar
ray(24, 25, 26)), Array(Array(7, 8, 9), Array(17, 18, 19), Array(27, 28,
 29)), Array(Array(31, 32, 33), Array(41, 42, 43), Array(51, 52, 53)), A
rray(Array(34, 35, 36), Array(44, 45, 46), Array(54, 55, 56)), Array(Arr
ay(37, 38, 39), Array(47, 48, 49), Array(57, 58, 59)), Array(Array(61, 6
2, 63), Array(71, 72, 73), Array(81, 82, 83)), Array(Array(64, 65, 66),
Array(74, 75, 76), Array(84, 85, 86)), Array(Array(67, 68, 69), Array(77
, 78, 79), Array(87, 88, 89)))

scala> res12.map(_.flatten)
res13: Array[Array[Int]] = Array(Array(1, 2, 3, 11, 12, 13, 21, 22, 23),
 Array(4, 5, 6, 14, 15, 16, 24, 25, 26), Array(7, 8, 9, 17, 18, 19, 27,
28, 29), Array(31, 32, 33, 41, 42, 43, 51, 52, 53), Array(34, 35, 36, 44
, 45, 46, 54, 55, 56), Array(37, 38, 39, 47, 48, 49, 57, 58, 59), Array(
61, 62, 63, 71, 72, 73, 81, 82, 83), Array(64, 65, 66, 74, 75, 76, 84, 8
5, 86), Array(67, 68, 69, 77, 78, 79, 87, 88, 89))

または、ワンライナーとして:

grid.map(_.grouped(3).toArray).grouped(3).toArray.map(_.transpose).flatten.map(_.flatten)
于 2013-02-26T14:49:32.793 に答える
3
val n: Array[Array[Int]] =
  grid.grouped(3)
      .toArray
      .flatMap(_.map(_.grouped(3).toArray)
                .transpose
                .map(_.flatten))

n.foreach(r => {r.foreach(e => print(e + " ")); println})

// 1 2 3 11 12 13 21 22 23 
// 4 5 6 14 15 16 24 25 26 
// 7 8 9 17 18 19 27 28 29 
// 31 32 33 41 42 43 51 52 53 
// 34 35 36 44 45 46 54 55 56 
// 37 38 39 47 48 49 57 58 59 
// 61 62 63 71 72 73 81 82 83 
// 64 65 66 74 75 76 84 85 86 
// 67 68 69 77 78 79 87 88 89

対応するものをスコープtoArrayに入れることで、明示的な呼び出しを削除できるはずです。implicit def

于 2013-02-26T14:27:40.067 に答える
2

これは、短くて効率的な解決策であり、最短で最も効率的な解決策になる可能性があります。

scala> val matrix = Array.tabulate(9, 9){ (r, c) => grid(r/3*3+c/3)(r%3*3+c%3) }
matrix: Array[Array[Int]] = 
Array(Array(1, 2, 3, 11, 12, 13, 21, 22, 23), 
      Array(4, 5, 6, 14, 15, 16, 24, 25, 26), 
      Array(7, 8, 9, 17, 18, 19, 27, 28, 29), 
      Array(31, 32, 33, 41, 42, 43, 51, 52, 53), 
      Array(34, 35, 36, 44, 45, 46, 54, 55, 56), 
      Array(37, 38, 39, 47, 48, 49, 57, 58, 59), 
      Array(61, 62, 63, 71, 72, 73, 81, 82, 83), 
      Array(64, 65, 66, 74, 75, 76, 84, 85, 86), 
      Array(67, 68, 69, 77, 78, 79, 87, 88, 89)
)
于 2013-02-27T03:47:29.463 に答える
2

これはどうですか?

type Grid = Array[Array[Int]]

def transform(grid: Grid): Grid = {
  def transformLine(grid: Grid) =
    grid.map(_.grouped(3).toArray).transpose.map(_.flatten)
  grid.grouped(3).flatMap(transformLine).toArray
}

scala> transform(grid) map(_.deep) foreach println
Array(1, 2, 3, 11, 12, 13, 21, 22, 23)
Array(4, 5, 6, 14, 15, 16, 24, 25, 26)
Array(7, 8, 9, 17, 18, 19, 27, 28, 29)
Array(31, 32, 33, 41, 42, 43, 51, 52, 53)
Array(34, 35, 36, 44, 45, 46, 54, 55, 56)
Array(37, 38, 39, 47, 48, 49, 57, 58, 59)
Array(61, 62, 63, 71, 72, 73, 81, 82, 83)
Array(64, 65, 66, 74, 75, 76, 84, 85, 86)
Array(67, 68, 69, 77, 78, 79, 87, 88, 89)

多くの暗黙的な変換と中間結果のために完全に非効率的ですが、機能的であり、1秒間に何百回も行う必要がない限り問題にはなりません...

于 2013-02-26T14:26:44.863 に答える
1

一行で:

grid.grouped(3).map(g => g.transpose.grouped(3).map(_.flatten.sorted)).flatten.toArray

res25: Array[Array[Int]] = Array(Array(1, 2, 3, 11, 12, 13, 21, 22, 23), Array(4 , 5, 6, 14, 15, 16, 24, 25 , 26), 配列(7, 8, 9, 17, 18, 19, 27, 28, 29), 配列(3 1, 32, 33, 41, 42, 43, 51, 52, 53), 配列(34 、35、36、44、45、46、54、55、56)、配列(37、38、39、47、48、49、57、58、59)、配列(61、62、63、71、 72、73、81、82、83)、配列(64、65、66、74、75、76、84、85、86)、配列(67、68、69、77、78、79、87、88、 89))

于 2013-02-26T14:36:57.693 に答える
1

素早く汚い(しかし機能的な)ハック:

(0 until grid(0).size/3).toArray.
  map(i =>
    grid.flatMap(a => a.drop(i*3).take(3))
  )

gridあなたが提供している場合、これは以下をもたらします:

Array(
  Array(1, 2, 3, 11, 12, 13, 21, 22, 23, /*...*/, 71, 72, 73, 81, 82, 83),
  Array(4, 5, 6, 14, 15, 16, 24, 25, 26, /*...*/, 74, 75, 76, 84, 85, 86), 
  Array(7, 8, 9, 17, 18, 19, 27, 28, 29, /*...*/, 77, 78, 79, 87, 88, 89)
)
于 2013-02-26T14:10:14.073 に答える