2013-02-26 40 views
2

比方說,我有以下矩陣:集團矩陣9x9的元素融入到3行3周的cols斯卡拉


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的解決方案

 
alg1 in Cycles: 10 Time: 2712683ns Memory: 459572 
alg1 in Cycles: 100 Time: 914297ns Memory: 458191 
alg1 in Cycles: 1000 Time: 85102ns Memory: 457944 
alg1 in Cycles: 10000 Time: 68742ns Memory: 457943 

@Daniel C.索布拉爾解決方案

 
alg2 in Cycles: 10 Time: 3747031ns Memory: 458889 
alg2 in Cycles: 100 Time: 1796564ns Memory: 457951 
alg2 in Cycles: 1000 Time: 186215ns Memory: 457220 
alg2 in Cycles: 10000 Time: 122642ns Memory: 456708 

@Or派勒斯的解決方案

 
alg3 in Cycles: 10 Time: 741475ns Memory: 457472 
alg3 in Cycles: 100 Time: 542181ns Memory: 457914 
alg3 in Cycles: 1000 Time: 248020ns Memory: 457911 
alg3 in Cycles: 10000 Time: 119105ns Memory: 457919 

@Hbf解決方案

 
alg4 in Cycles: 10 Time: 179093ns Memory: 457472 
alg4 in Cycles: 100 Time: 121072ns Memory: 457069 
alg4 in Cycles: 1000 Time: 78123ns Memory: 456719 
alg4 in Cycles: 10000 Time: 75948ns Memory: 455913 

@Eastsun解決方案

 
alg5 in Cycles: 10 Time: 144037ns Memory: 457512 
alg5 in Cycles: 100 Time: 40672ns Memory: 457059 
alg5 in Cycles: 1000 Time: 42236ns Memory: 456119 
alg5 in Cycles: 10000 Time: 46480ns Memory: 455952 

我測試過它的MacMini(2012)。內存結果是真的奇怪,於是來源都在這裏,如果有一些嚴重的錯誤和反模式,請告訴我=)https://github.com/Stimphonier/MatrixBench

+0

我想這不是'陣列(4,5,6,14,15,16,21,22,23)'你的意思'陣列(4,5,6,14 ,15,16,24,25,26),並且最後的'...'實際上應該是每個內部數組後面的三個'...',對吧? – Hbf 2013-02-26 14:11:31

+0

另請參閱http://stackoverflow.com/questions/5193781/java-scala-library-for-algebra-mathematics – oluies 2013-02-26 15:19:27

+0

如果您快速基準(時間,也許還有內存消耗)各種提出的解決方案並報告結果。它不應該花很長時間,它肯定會對社區有所幫助。 – 2013-02-27 09:19:08

回答

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) 
) 
+0

謝謝,真的很喜歡你的解決方案 – 4lex1v 2013-02-28 06:29:23

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) 
) 
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) 

完全低效的,因爲大量的隱式轉換和中間結果的,但它的功能,除非你需要做幾百次在第二不應該是一個問題...

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 

應該可以通過將相應的implicit def納入範圍來刪除明確的toArray調用。

1

在一行:

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

res25:數組[數組[INT]] =陣列(陣列(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),陣列(3 1,32, 33,31,42,43,51,52,53),陣列(34,35,36,44,45,46,54,55,56),A 陣列陣列(61,62,63,71,72,73,81,82, 83),陣列(64,65,66,74,75,76,84,85,86),陣列),Array(67,68,69,77,78,79,87, ,88,89))

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 
4

組和轉置。我將在那裏找出正確的順序來顯示REPL會話。

首先,您的數據中有一個分組 - 您清楚地用空格表示。每三行,每行三行內。所以我們要做的第一件事就是明確分組。

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) 
+0

謝謝你的解釋,不知道轉置方法=) – 4lex1v 2013-02-28 06:39:56