2017-05-05 52 views
1

我有一個3維陣列(array[x][y][z]x y z罐柔性)夫特 - 如何減少矩陣

var array = [ [[1,1,1],[0,0,0],[1,1,1]], 
       [[1,0,1],[1,0,1],[1,0,1]], 
       [[1,1,1],[0,0,0],[1,1,1]] 
      ] 

如何減少3D到2D到:array[z][y]

[3,1,3],[2,0,2],[3,1,3] 

予讀出的指令here但無法弄清楚如何應用於我的。

更新時間: 這是由於邏輯 enter image description here

enter image description here

+5

將第一個數組轉換爲第二個數組的操作是什麼? – matt

+0

在Python中,我正在使用'add.reduce(array,0)'。以下是一個https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.reduce.html – hoangpx

+4

我知道你正在做某種矩陣代數的解釋,但直到你能提供關於將第一個數組轉換爲第二個數組的步驟說明,您無法對其進行編碼。這與Swift「reduce」本身無關。教_me_把第一個數組變成第二個數組,然後我可以嘗試教計算機去做。 – matt

回答

2

讓我們開始(「CW」是指逐列):

extension Array where Element == [[Int]] { 
    func cwsum(_ ix1:Int, _ ix2:Int) -> Int { 
     return reduce(0) {$0 + $1[ix1][ix2]} 
    } 
} 

然後,如果陣列是:

let array = [[[1,1,1],[0,0,0],[1,1,1]], 
      [[1,0,1],[1,0,1],[1,0,1]], 
      [[1,1,1],[0,0,0],[1,1,1]]] 

...那麼答案是:

[[array.cwsum(0,0), array.cwsum(1,0), array.cwsum(2,0)], 
[array.cwsum(0,1), array.cwsum(1,1), array.cwsum(2,1)], 
[array.cwsum(0,2), array.cwsum(1,2), array.cwsum(2,2)]] 
// [[3, 1, 3], [2, 0, 2], [3, 1, 3]] 

但是等等 - 我想我在這裏看到一個模式!我們可以重寫,如果沒有硬編碼的指標,如:

var result = [[Int]]() 
for j in 0..<3 { 
    var r1 = [Int]() 
    for i in 0..<3 { 
     r1.append(array.cwsum(i,j)) 
    } 
    result.append(r1) 
} // result is now [[3, 1, 3], [2, 0, 2], [3, 1, 3]] 

好了,但在這裏我們可以循環和append,我們可以map代替,從而把i到地圖變量:

var result = [[Int]]() 
for j in 0..<3 { 
    result.append((0..<3).map{i in array.cwsum(i,j)}) 
} 

但是,我們可以做到這一點爲j,以及 - 因此它成爲一個單行:

result = (0..<3).map{j in (0..<3).map{i in array.cwsum(i,j)}} 
+0

這完全符合我的問題。但是,如果'x,y,z'可以靈活地使用'array [x] [y] [z]'',您可以使它更普遍嗎? – hoangpx

+1

@hoangpx您是程序員,_you_使其更加通用! – matt

+0

我會盡快更新。我從一條線瞭解了很多。謝謝 – hoangpx

0

let matrix = [ 
    [[1,1,1],[0,0,0],[1,1,1]], 
    [[1,0,1],[1,0,1],[1,0,1]], 
    [[1,1,1],[0,0,0],[1,1,1]] 
] 

讓計算這些

let all = matrix.joined().enumerated() 

let a = all.filter { $0.offset % 3 == 0 }.map { $0.element[0] }.reduce(0, +) 
let b = all.filter { $0.offset % 3 == 1 }.map { $0.element[0] }.reduce(0, +) 
let c = all.filter { $0.offset % 3 == 2 }.map { $0.element[0] }.reduce(0, +) 

let d = all.filter { $0.offset % 3 == 0 }.map { $0.element[1] }.reduce(0, +) 
let e = all.filter { $0.offset % 3 == 1 }.map { $0.element[1] }.reduce(0, +) 
let f = all.filter { $0.offset % 3 == 2 }.map { $0.element[1] }.reduce(0, +) 

let g = all.filter { $0.offset % 3 == 0 }.map { $0.element[2] }.reduce(0, +) 
let h = all.filter { $0.offset % 3 == 1 }.map { $0.element[2] }.reduce(0, +) 
let i = all.filter { $0.offset % 3 == 2 }.map { $0.element[2] }.reduce(0, +) 

終於讓PU t時的值加在一起

let res = [[a, b, c], [d, e, f], [g, h, i]] 
1

因爲它聽起來像你正在尋找一個函數式編程的一行,這裏是你的答案:

array.indices.map{ j in array.indices.map{ i in array.map{ $0[i][j] }.reduce(0, +) } } 

它基本上與此相同的代碼,它們雖然多更長的時間,我認爲閱讀起來更容易,並且讓我更少想到理由。

func flatten2(_ array:[[[Int]]]) -> [[Int]] 
{ 
    var result:[[Int]] = [] 
    for j in 0..<array.count 
    { 
     var row:[Int] = [] 
     for i in 0..<array.count 
     { 
      row.append(array.map{ $0[i][j] }.reduce(0, +)) 
     } 
     result.append(row) 
    } 
    return result 
} 

牢記一個班輪將接管兩個數量級較長的編譯,因爲斯威夫特的編譯器是不是很功能性和封閉編程優化,所以它必須建立巨大的過載樹解析那個表達。因爲我懷疑這是CS決賽的練習考題中的一個問題,所以請讓您的助教簡單一些,並使用多線程。通過形成效用函數作爲矩陣式陣列上的延伸

+1

更好地使用你的數組索引。 'array.indices.map {J用array.indices.map {我在array.map {$ 0 [i] [j]}。降低(0,+)}}' –

+0

@LeoDabus好主意!我編輯了答案 –

+0

好吧,'array.indices'是最外層數組的索引,而不是嵌套數組的索引(甚至可能有不同的維數)。因此,使用'array.indices'作爲遍歷二級或三級數組的序列對我來說似乎不合邏輯。 –

0

後嘗試小時。這是我的輸出,它非常簡單,與reduce無關。 3d陣列的輸入是靈活的x,y,z

let x = array.count 
    let y = array[0].count 
    let z = array[0][0].count 

    var final = Array(repeating: Array(repeating: 0, count: y), count: z) 
    for i in 0..<z { 
     for ii in 0..<y { 
      var sum = 0 
      for iii in 0..<x { 
       sum = sum + array[iii][ii][i] 
      } 
      final[i][ii] = sum 
     } 

    }