假设我有一些函数,我想使用多维数组(例如 Tensor 类)填充我的数据结构:
class Tensor {
init<A>(array:A) { /* ... */ }
}
虽然我可以添加一个 shape
参数,但我更愿意自动计算数组本身的维度。如果您先验地知道维度,那么读取它就很简单了:
let d1 = array.count
let d2 = array[0].count
但是,如何对 N 维数组执行此操作不太清楚。我在想可能有一种方法可以通过扩展 Array 类来实现:
extension Int {
func numberOfDims() -> Int {
return 0
}
}
extension Array {
func numberOfDims() -> Int {
return 1+Element.self.numberOfDims()
}
}
不幸的是,这不会(理所当然地)编译,因为 numberOfDims
没有为大多数类型定义。但是,我看不到任何限制 Element
的方法,因为 Arrays-of-Arrays 使事情变得复杂。
我希望其他人可能对如何解决这个问题有一些见解(或解释为什么这是不可能的)。
最佳答案
如果你想获得嵌套数组的深度(Swift 的标准库技术上不为你提供多维数组,只提供锯齿状数组)——那么,如 this Q&A 所示,您可以使用“虚拟协议(protocol)”和类型转换。
protocol _Array {
var nestingDepth: Int { get }
}
extension Array : _Array {
var nestingDepth: Int {
return 1 + ((first as? _Array)?.nestingDepth ?? 0)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2, 3], [4]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[4], [5]]]
print(c.nestingDepth) // 3
(我相信这种方法在您最初发布问题时仍然有效)
在 Swift 3 中,这也可以在没有虚拟协议(protocol)的情况下实现,而是通过转换为 [Any]
来实现。但是,如链接的问答中所述,这是低效的,因为它需要遍历整个数组才能将每个元素装入存在的容器中。
另请注意,此实现假定您是在同类嵌套数组上调用它。 As Paul notes ,它不会为 [[[1], 2], 3]
给出正确答案。
如果需要考虑这一点,您可以编写一个递归方法,该方法将遍历每个嵌套数组并返回嵌套的最小深度。
protocol _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int
}
extension Array : _Array {
func _nestingDepth(minimumDepth: Int?, currentDepth: Int) -> Int {
// for an empty array, the minimum depth is the current depth, as we know
// that _nestingDepth is called where currentDepth <= minimumDepth.
guard !isEmpty else { return currentDepth }
var minimumDepth = minimumDepth
for element in self {
// if current depth has exceeded minimum depth, then return the minimum.
// this allows for the short-circuiting of the function.
if let minimumDepth = minimumDepth, currentDepth >= minimumDepth {
return minimumDepth
}
// if element isn't an array, then return the current depth as the new minimum,
// given that currentDepth < minimumDepth.
guard let element = element as? _Array else { return currentDepth }
// get the new minimum depth from the next nesting,
// and incrementing the current depth.
minimumDepth = element._nestingDepth(minimumDepth: minimumDepth,
currentDepth: currentDepth + 1)
}
// the force unwrap is safe, as we know array is non-empty, therefore minimumDepth
// has been assigned at least once.
return minimumDepth!
}
var nestingDepth: Int {
return _nestingDepth(minimumDepth: nil, currentDepth: 1)
}
}
let a = [1, 2, 3]
print(a.nestingDepth) // 1
let b = [[1], [2], [3]]
print(b.nestingDepth) // 2
let c = [[[1], [2]], [[3]], [[5], [6]]]
print(c.nestingDepth) // 3
let d: [Any] = [ [[1], [2], [[3]] ], [[4]], [5] ]
print(d.nestingDepth) // 2 (the minimum depth is at element [5])
关于swift - Swift计算多维数组的维数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33664208/