如何更快速地转置数组?
How to transpose an array more Swiftly?
我想像这样转置一个数组:
原数组:
[
[1,2,3],
[4,5,6],
[7,8,9]
]
结果:
[
1,4,7,
2,5,8,
3,6,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
(它基本上是网格状布局中的一堆正方形)作为棋盘游戏的棋盘。要编辑网格节点的内容,我需要传入精灵节点的一维数组,而不是二维数组。
为了让我的生活更轻松,我将模型对象存储在二维数组中。这样,我就可以通过以下方式参考左边 5 个方块和顶部 2 个方块的正方形:
modelObjects[5][2]
如果我使用 .flatMap { [=15=] }
展平 2D 数组并将结果传递给网格节点,modelObjects[5][2]
将显示为距左侧 2 个方格和距顶部 5 个方格。
这不是 this 的重复,因为该问题似乎有一定数量的数组可供使用。尽管我可以将我的二维数组放入一个循环中,并执行那些 enumerate().map {...}
的操作,但这似乎是一个非常冗长的方法。我认为必须有更简单的二维数组来做到这一点。
你可以通过转置你的二维矩阵得到你想要的结果,例如,使用这个函数:
func matrixTranspose<T>(_ matrix: [[T]]) -> [[T]] {
if matrix.isEmpty {return matrix}
var result = [[T]]()
for index in 0..<matrix.first!.count {
result.append(matrix.map{[=10=][index]})
}
return result
}
然后应用 flatten
(joined
in swift 3)。
let arr = [[1,2,3],[4,5,6],[7,8,9]]
print(matrixTranspose(arr))
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
print(matrixTranspose(arr).flatMap{[=11=]})
// [1, 4, 7, 2, 5, 8, 3, 6, 9]
扩展版本:
extension Collection where Self.Iterator.Element: Collection {
var transpose: Array<Array<Self.Iterator.Element.Iterator.Element>> {
var result = Array<Array<Self.Iterator.Element.Iterator.Element>>()
if self.isEmpty {return result}
var index = self.first!.startIndex
while index != self.first!.endIndex {
var subresult = Array<Self.Iterator.Element.Iterator.Element>()
for subarray in self {
subresult.append(subarray[index])
}
result.append(subresult)
index = self.first!.index(after: index)
}
return result
}
}
有使用
let arr = [[1,2,3],[4,5,6],[7,8,9]]
print(arr.transpose)
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
这是对 Shadow Of's 的改进:
extension Collection where Self.Iterator.Element: RandomAccessCollection {
// PRECONDITION: `self` must be rectangular, i.e. every row has equal size.
func transposed() -> [[Self.Iterator.Element.Iterator.Element]] {
guard let firstRow = self.first else { return [] }
return firstRow.indices.map { index in
self.map{ [=10=][index] }
}
}
}
let matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
matrix.transposed().forEach{ print([=10=]) }
我想像这样转置一个数组:
原数组:
[
[1,2,3],
[4,5,6],
[7,8,9]
]
结果:
[
1,4,7,
2,5,8,
3,6,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
(它基本上是网格状布局中的一堆正方形)作为棋盘游戏的棋盘。要编辑网格节点的内容,我需要传入精灵节点的一维数组,而不是二维数组。
为了让我的生活更轻松,我将模型对象存储在二维数组中。这样,我就可以通过以下方式参考左边 5 个方块和顶部 2 个方块的正方形:
modelObjects[5][2]
如果我使用 .flatMap { [=15=] }
展平 2D 数组并将结果传递给网格节点,modelObjects[5][2]
将显示为距左侧 2 个方格和距顶部 5 个方格。
这不是 this 的重复,因为该问题似乎有一定数量的数组可供使用。尽管我可以将我的二维数组放入一个循环中,并执行那些 enumerate().map {...}
的操作,但这似乎是一个非常冗长的方法。我认为必须有更简单的二维数组来做到这一点。
你可以通过转置你的二维矩阵得到你想要的结果,例如,使用这个函数:
func matrixTranspose<T>(_ matrix: [[T]]) -> [[T]] {
if matrix.isEmpty {return matrix}
var result = [[T]]()
for index in 0..<matrix.first!.count {
result.append(matrix.map{[=10=][index]})
}
return result
}
然后应用 flatten
(joined
in swift 3)。
let arr = [[1,2,3],[4,5,6],[7,8,9]]
print(matrixTranspose(arr))
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
print(matrixTranspose(arr).flatMap{[=11=]})
// [1, 4, 7, 2, 5, 8, 3, 6, 9]
扩展版本:
extension Collection where Self.Iterator.Element: Collection {
var transpose: Array<Array<Self.Iterator.Element.Iterator.Element>> {
var result = Array<Array<Self.Iterator.Element.Iterator.Element>>()
if self.isEmpty {return result}
var index = self.first!.startIndex
while index != self.first!.endIndex {
var subresult = Array<Self.Iterator.Element.Iterator.Element>()
for subarray in self {
subresult.append(subarray[index])
}
result.append(subresult)
index = self.first!.index(after: index)
}
return result
}
}
有使用
let arr = [[1,2,3],[4,5,6],[7,8,9]]
print(arr.transpose)
// [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
这是对 Shadow Of's
extension Collection where Self.Iterator.Element: RandomAccessCollection {
// PRECONDITION: `self` must be rectangular, i.e. every row has equal size.
func transposed() -> [[Self.Iterator.Element.Iterator.Element]] {
guard let firstRow = self.first else { return [] }
return firstRow.indices.map { index in
self.map{ [=10=][index] }
}
}
}
let matrix = [
[1, 2, 3, 4],
[5, 6, 7, 8],
[9, 10, 11, 12],
]
matrix.transposed().forEach{ print([=10=]) }