gpt4 book ai didi

arrays - N维数组swift

转载 作者:搜寻专家 更新时间:2023-11-01 06:27:58 25 4
gpt4 key购买 nike

有什么方法可以在 swift 中创建一个 n 维数组吗?我希望能够创建一个创建 n 维数组的函数,但我不知道该怎么做。

基本上是这样的:

func ndarray <T> (dimensions: Int...) -> [[T]] { // What do I tell it I return?
var out
for d in dimensions {
out = Array<T>(repeating: out, count: d)
}
return out
}

上面的代码由于明显的原因不起作用,但我认为它指出了我遇到的主要问题:

  • 如何定义返回类型
  • 我如何实际创建数组
  • 创建后如何遍历和填充数组

最佳答案

这是 N 维数组的实现。其内部使用普通数组存储,并将多维索引转换为内部数组的单个索引。

struct NDimArray<T> {
let dimensions: [Int]
var data: [T]

init(dimensions: Int..., initialValue: T) {
self.dimensions = dimensions
data = Array(repeating: initialValue, count: dimensions.reduce(1, *))
}

init(dimensions: Int..., initUsing initializer: () -> T) {
self.dimensions = dimensions
data = (0 ..< dimensions.reduce(1, *)).map { _ in initializer() }
}

// Compute index into data from indices
private func computeIndex(_ indices: [Int]) -> Int {
guard indices.count == dimensions.count else { fatalError("Wrong number of indices: got \(indices.count), expected \(dimensions.count)") }
zip(dimensions, indices).forEach { dim, idx in
guard (0 ..< dim) ~= idx else { fatalError("Index out of range") }
}

var idx = indices
var dims = dimensions
var product = 1
var total = idx.removeLast()
while !idx.isEmpty {
product *= dims.removeLast()
total += (idx.removeLast() * product)
}

return total
}

subscript(_ indices: Int...) -> T {
get {
return data[computeIndex(indices)]
}
set {
data[computeIndex(indices)] = newValue
}
}
}

示例:

// Create a 3 x 4 x 5 array of String with initial value ""

var arr = NDimArray<String>(dimensions: 3, 4, 5, initialValue: "")
for x in 0 ..< 3 {
for y in 0 ..< 4 {
for z in 0 ..< 5 {
// Encode indices in the string
arr[x, y, z] = "(\(x),\(y),\(z))"
}
}
}


// Show internal storage of data
print(arr.data)

["(0,0,0)", "(0,0,1)", "(0,0,2)", "(0,0,3)", "(0,0,4)", "(0,1,0)", "(0,1,1)", "(0,1,2)", "(0,1,3)", "(0,1,4)", "(0,2,0)", "(0,2,1)", "(0,2,2)", "(0,2,3)", "(0,2,4)", "(0,3,0)", "(0,3,1)", "(0,3,2)", "(0,3,3)", "(0,3,4)", "(1,0,0)", "(1,0,1)", "(1,0,2)", "(1,0,3)", "(1,0,4)", "(1,1,0)", "(1,1,1)", "(1,1,2)", "(1,1,3)", "(1,1,4)", "(1,2,0)", "(1,2,1)", "(1,2,2)", "(1,2,3)", "(1,2,4)", "(1,3,0)", "(1,3,1)", "(1,3,2)", "(1,3,3)", "(1,3,4)", "(2,0,0)", "(2,0,1)", "(2,0,2)", "(2,0,3)", "(2,0,4)", "(2,1,0)", "(2,1,1)", "(2,1,2)", "(2,1,3)", "(2,1,4)", "(2,2,0)", "(2,2,1)", "(2,2,2)", "(2,2,3)", "(2,2,4)", "(2,3,0)", "(2,3,1)", "(2,3,2)", "(2,3,3)", "(2,3,4)"]

print(arr[2, 2, 2])  // "(2,2,2)"
print(arr[3, 0, 0]) // Fatal error: Index out of range
print(arr[0, 4, 0]) // Fatal error: Index out of range
print(arr[2]) // Fatal error: Wrong number of indices: got 1, expected 3

使用引用类型初始化数组

正如@DuncanC 在评论中指出的那样,在使用引用类型的值初始化数组时必须小心,因为数组将填充对对象的引用,并且在任何索引处修改对象都会修改所有

为了解决这个问题,我添加了第二个初始化程序:

init(dimensions: Int..., initUsing initializer: () -> T)

它有一个闭包 () -> T 可以用来为数组的每个元素创建一个新对象。

例如:

class Person {
var name = ""
}

// Pass a closure which creates a `Person` instance to fill the array
// with 25 person objects
let arr = NDimArray(dimensions: 5, 5, initUsing: { Person() })
arr[3, 3].name = "Fred"
arr[2, 2].name = "Wilma"

print(arr[3, 3].name, arr[2, 2].name)

Fred Wilma

关于arrays - N维数组swift,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51447194/

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