Swift: 改变结构中的数组
Swift: Mutating array in struct
我正在尝试在 Swift 中创建矩阵 class,但我在 setRow()
函数的 self.data[row * columns..<(row + 1) * columns] = data
行收到错误。错误是 'Cannot assign value of type '[Double]' 键入 'ArraySlice''
struct Matrix: CustomStringConvertible {
let rows:Int
let columns:Int
var data:[Double]
// Description
public var description: String {
var description = ""
for r in 0..<rows {
description += data[r * columns..<(r + 1) * columns].description + "\n"
}
return description
}
// Initialisation
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
self.data = Array(repeating: 0.0, count: rows * columns)
}
init(rows: Int, columns: Int, data:[Double]) {
assert(data.count == (rows * columns),"Number of elements must equal rows * columns")
self.rows = rows
self.columns = columns
self.data = data
}
// Validity
func validRow(row: Int) -> Bool {
return row > 0 && row < rows
}
func validColumn(column: Int) -> Bool {
return column > 0 && column < columns
}
func validIndex(row: Int, column: Int) -> Bool {
return validRow(row: row) && validColumn(column: column)
}
// Setters and getters
func get(row: Int, column: Int) -> Double {
assert(validIndex(row: row,column: column), "Index out of range")
return data[(row * columns) + column]
}
mutating func set(row: Int, column: Int, value: Double) {
assert(validIndex(row: row,column: column), "Index out of range")
data[(row * columns) + column] = value
}
func getRow(row: Int) -> [Double] {
assert(validRow(row: row), "Index out of range")
return Array(data[row * columns..<(row + 1) * columns])
}
mutating func setRow(row: Int, data:[Double]) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
self.data[row * columns..<(row + 1) * columns] = data
}
// Swapping
mutating func swapRow(row1: Int, row2: Int) {
assert(validRow(row: row1) && validRow(row: row2), "Index out of range")
let holder = getRow(row: row2)
setRow(row: row2, data: getRow(row: row1))
setRow(row: row1, data: holder)
}
}
听起来很简单。您不想在函数中设置 Double
而不是 [Double]
吗?
mutating func setRow(row: Int, data: Double) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
self.data[row * columns..<(row + 1) * columns] = data
}
如错误所述,Array
的范围下标处理 ArraySlice
,而不是 Array
。
一个解决方案,如, is to just create a slice of the entire input array. This can be done by subscripting with the array's indices
:
mutating func setRow(row: Int, data newData: [Double]) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
data[row * columns ..< (row + 1) * columns] = newData[newData.indices]
}
或者在 Swift 4 中,你可以利用 the ...
'operator',它做同样的事情:
data[row * columns ..< (row + 1) * columns] = newData[...]
但是在我看来,更好的工具是 replaceSubrange(_:with:)
:
mutating func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C)
where Element == C.Element, C : Collection
因为它允许您处理任意 Collection
个新元素,这意味着您还可以使 setRow
通用:
mutating func setRow<C : Collection>(row: Int, data newData: C)
where C.Iterator.Element == Double { // <- in Swift 4, remove ".Iterator"
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
data.replaceSubrange(row * columns ..< (row + 1) * columns, with: newData)
}
我正在尝试在 Swift 中创建矩阵 class,但我在 setRow()
函数的 self.data[row * columns..<(row + 1) * columns] = data
行收到错误。错误是 'Cannot assign value of type '[Double]' 键入 'ArraySlice''
struct Matrix: CustomStringConvertible {
let rows:Int
let columns:Int
var data:[Double]
// Description
public var description: String {
var description = ""
for r in 0..<rows {
description += data[r * columns..<(r + 1) * columns].description + "\n"
}
return description
}
// Initialisation
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
self.data = Array(repeating: 0.0, count: rows * columns)
}
init(rows: Int, columns: Int, data:[Double]) {
assert(data.count == (rows * columns),"Number of elements must equal rows * columns")
self.rows = rows
self.columns = columns
self.data = data
}
// Validity
func validRow(row: Int) -> Bool {
return row > 0 && row < rows
}
func validColumn(column: Int) -> Bool {
return column > 0 && column < columns
}
func validIndex(row: Int, column: Int) -> Bool {
return validRow(row: row) && validColumn(column: column)
}
// Setters and getters
func get(row: Int, column: Int) -> Double {
assert(validIndex(row: row,column: column), "Index out of range")
return data[(row * columns) + column]
}
mutating func set(row: Int, column: Int, value: Double) {
assert(validIndex(row: row,column: column), "Index out of range")
data[(row * columns) + column] = value
}
func getRow(row: Int) -> [Double] {
assert(validRow(row: row), "Index out of range")
return Array(data[row * columns..<(row + 1) * columns])
}
mutating func setRow(row: Int, data:[Double]) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
self.data[row * columns..<(row + 1) * columns] = data
}
// Swapping
mutating func swapRow(row1: Int, row2: Int) {
assert(validRow(row: row1) && validRow(row: row2), "Index out of range")
let holder = getRow(row: row2)
setRow(row: row2, data: getRow(row: row1))
setRow(row: row1, data: holder)
}
}
听起来很简单。您不想在函数中设置 Double
而不是 [Double]
吗?
mutating func setRow(row: Int, data: Double) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
self.data[row * columns..<(row + 1) * columns] = data
}
如错误所述,Array
的范围下标处理 ArraySlice
,而不是 Array
。
一个解决方案,如indices
:
mutating func setRow(row: Int, data newData: [Double]) {
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
data[row * columns ..< (row + 1) * columns] = newData[newData.indices]
}
或者在 Swift 4 中,你可以利用 the ...
'operator',它做同样的事情:
data[row * columns ..< (row + 1) * columns] = newData[...]
但是在我看来,更好的工具是 replaceSubrange(_:with:)
:
mutating func replaceSubrange<C>(_ subrange: Range<Int>, with newElements: C)
where Element == C.Element, C : Collection
因为它允许您处理任意 Collection
个新元素,这意味着您还可以使 setRow
通用:
mutating func setRow<C : Collection>(row: Int, data newData: C)
where C.Iterator.Element == Double { // <- in Swift 4, remove ".Iterator"
assert(validRow(row: row), "Index out of range")
assert(data.count == columns, "Data must be same length ans the number of columns")
data.replaceSubrange(row * columns ..< (row + 1) * columns, with: newData)
}