gpt4 book ai didi

swift - 在 Swift 中计算多维数组的维数

转载 作者:行者123 更新时间:2023-11-30 10:26:47 25 4
gpt4 key购买 nike

假设我有一些函数想要使用多维数组(例如张量类)填充我的数据结构:

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 的方法,因为数组的数组使事情变得复杂。

我希望其他人可能对如何解决这个问题有一些见解(或解释为什么这是不可能的)。

最佳答案

如果您希望获取嵌套数组的深度(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/59997731/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com