【问题标题】:Swift - how to reduce matrixSwift - 如何减少矩阵
【发布时间】:2017-10-04 06:04:36
【问题描述】:

我有一个 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 的说明,但不知道如何申请我的。

更新: 这是逻辑

【问题讨论】:

  • 将第一个数组变成第二个数组的数学运算是什么?
  • 在python中,我使用add.reduce(array, 0)。这是docs.scipy.org/doc/numpy/reference/generated/…的解释
  • 我知道您正在做某种矩阵代数,但在您提供将第一个数组转换为第二个数组的分步说明之前,您无法编写代码。这与 Swift reduce 本身无关。教把第一个数组变成第二个数组,然后我可以试着教电脑去做。
  • 除非您清楚地分享和解释您的算法,并附上解释,否则我们无法为您提供帮助。
  • 我更新了问题。希望你能理解。

标签: swift matrix reduce


【解决方案1】:

让我们首先形成一个实用函数作为矩阵式数组的扩展(“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 转换为map 变量:

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

【讨论】:

  • 这完全满足了我的问题。但是,当x, y, z 可以灵活使用时,您能否将array[x][y][z] 的点赞更普遍
  • @hoangpx 你是程序员,让它更通用!
  • 我会尽快更新。我从一行中学到了很多东西。谢谢
【解决方案2】:

因为听起来您正在寻找函数式编程单线,所以这是您的答案:

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
}

请记住,单行编译器的编译时间会多出两个数量级,因为 Swift 编译器对函数式和闭包式编程并不是很优化,因此它必须构造巨大的重载树来解析该表达式。由于我怀疑这是 CS 期末考试练习考试中的问题,请,请让你可怜的助教的生活更轻松,并使用多线。

【讨论】:

  • 更好地使用您的数组索引。 array.indices.map{ j in array.indices.map{ i in array.map{ $0[i][j] }.reduce(0, +) } }
  • 嗯,array.indices 是最外层数组的索引,而不是嵌套数组的索引(甚至可以有不同的维度)。因此,使用array.indices 作为迭代第二级或第三级数组的序列对我来说似乎不合逻辑。
  • @MartinR 我认为数组必须是方形的,否则操作变得未定义……我不确定
  • 您只需要在同一级别上的相同尺寸。当然,我不知道 OP 的确切要求,但 [ [[1,1,1,2],[0,0,0,2]], [[1,0,1,3],[1,0,1,4]], [[1,1,1,1],[0,0,0,0]] ] 将是一个数组,该操作对其有意义。
  • @MartinR 我的错误,在这种情况下我们应该遍历内部数组的索引,不是吗?
【解决方案3】:

鉴于此

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

最后让我们把值放在一起

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

【讨论】:

    【解决方案4】:

    经过数小时的尝试。这是我的输出,非常简单,与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
            }
    
        }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-03-07
      • 2015-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多