簡體   English   中英

Swift:在struct中修改數組

[英]Swift: Mutating array in struct

我試圖在Swift中創建一個Matrix類,但是在setRow()函數中的self.data[row * columns..<(row + 1) * columns] = data行上遇到了錯誤。 錯誤是“無法將類型'[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)
    }
}

如錯誤所述, Array的遠程下標處理ArraySlice而不是Array

正如@vacawama所說 ,一種解決方案是只創建整個輸入數組的一部分。 這可以通過用數組的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中,您可以利用... 'operator' ,它執行的功能完全相同:

data[row * columns ..< (row + 1) * columns] = newData[...]

但是,IMO,一個更好的工具是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)
}

聽起來很簡單。 您是否不想在函數中僅設置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
    }

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM