2017-05-05 46 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 
     } 

    }