一尘不染

如何更快速地转置数组?

swift

不久前我问过类似的问题。有人问我怎样才能变成这样的数组:

[[1,2,3],[4,5,6],[7,8,9]]

对此:

[1,2,3,4,5,6,7,8,9]

但是现在我想把相同的数组变成这个:

[1,4,7,2,5,8,3,6,9]

假设所有子数组具有相同的长度。

如果您尚未注意到,结果中的前三项就是这三个子数组中的第一项。结果中的第四,第五和第六项是每个子数组的第二项。

如果您仍然不了解,也许这会有所帮助:

原始数组:

[
    [1,2,3],
    [4,5,6],
    [7,8,9]
]

结果:

[
    1,4,7,
    2,5,8,
    3,6,9
]

此刻,我有这个:

func flatten(array: [[Int]]) -> [Int] {
    var flat = [Int]()
    for i in 0..<array[0].count {
        for subarray in array {
            flat.append(subarray[i])
        }
    }
    return flat
}

我认为那不是很花钱。如何快速进行此操作?

为了避免成为XY问题,这就是我要这样做的原因。

我正在开发一个棋盘游戏。我正在使用HLSpriteKit的棋盘游戏HLGridNode(基本上是一堆正方形的网格状布局)。要编辑网格节点的内容,我需要传递一个Sprite节点的1D数组,而不是2D数组。

为了使生活更轻松,我将模型对象存储在2D数组中。这样,我可以通过以下操作从左到左引用5个正方形,从上到顶部引用2个正方形。

modelObjects[5][2]

如果我使用展平2D数组.flatMap { $0 }并将结果传递到网格节点,则它modelObjects[5][2]看起来将是从左侧2个正方形和从顶部5个正方形。

这不是重复这个,因为这个问题似乎有数组与工作的明确的数量。尽管我可以将2D数组放入一个循环中并执行这些操作enumerate().map{...},但这似乎是一个漫长的过程。我认为使用2D阵列必须做得更简单。


阅读 287

收藏
2020-07-07

共1个答案

一尘不染

这里有一个改进的影子of的答案:

extension Collection where Self.Iterator.Element: RandomAccessCollection { 
    func transposed() -> [[Self.Iterator.Element.Iterator.Element]] {
        guard let firstRow = self.first else { return [] }
        return firstRow.indices.map { index in
            self.map{ $0[index] }
        }
    }
}

let matrix = [
    [1, 2, 3, 4],
    [5, 6, 7, 8],
    [9, 10, 11, 12],
]
matrix.transposed().forEach{ print($0) }
2020-07-07