简体   繁体   English

如何在Swift 4中声明数组索引的类型

[英]How do I declare the type of an array index in swift 4

Am trying to create a 2D lookup table with enums representing the axes of the table in swift 4, for example: 我正在尝试创建一个2D查找表,其中的枚举表示swift 4中表格的轴,例如:

enum ECT: Int {
  case cool = 0
  case normal
  case above_range
}

enum Load: Int {
  case idle = 0
  case cruise
  case wot
}

var timingRetard = [[Double?]](repeating: [nil,nil,nil], count 3)

(no, I'm not writing embedded PCM code in Swift (tho that would be fun!), but its a simple example for the swift construct I'm trying to use but haven't figured out the syntax) (不,我不是在Swift中编写嵌入式PCM代码(那会很有趣!),但这是我尝试使用的swift构造的一个简单示例,但是还没有弄清楚语法)

how can assign & retrieve values in the array using the enum as an index, eg assuming the element has already been created 如何使用枚举作为索引来分配和检索数组中的值,例如假设元素已经创建

timingRetard[cool][idle] = 0.0
timingRetard[cool][cruise] = 0.0
timingRetard[cool][wot] = 0.0
timingRetard[above_range][wot] = -8.0
timingRetard[normal][cruise] = 0.0

How do I declare index types of a Swift array to be only accessed by the enum types after init'ing the array given the number of enums for each axis? 如何在给定每个轴枚举数的情况下初始化数组后,如何声明Swift数组的索引类型只能由枚举类型访问? I figured I could add timingRetard to a struct and declare a subscript method to constrain the indexes to the enum types, but haven't gotten that to work either. 我以为可以在一个结构中添加TimingRetard并声明一个下标方法来将索引限制为枚举类型,但也没有做到这一点。

One way to achieve is to override subscript method in a struct. 一种实现的方法是在结构中覆盖下标方法。 It is explained much better here . 这里解释得更好。 I used the example mentioned in the link to solve your problem in this way: 我使用链接中提到的示例以这种方式解决您的问题:

enum ECT: Int{
    case cool = 0
    case normal
    case above_range
}

enum Load: Int {
    case idle = 0
    case cruise
    case wot
}

struct TimingRetard2D {
    let rows: Int, cols: Int
    private(set) var array:[Double?]

    init(rows: Int, cols: Int, repeating:Double?) {
        self.rows = rows
        self.cols = cols
        array = Array(repeating: repeating, count: rows * cols)
    }

    private func indexIsValid(row: Int, col: Int) -> Bool {
        return row >= 0 && row < rows && col >= 0 && col < cols
    }

    subscript(row: ECT, col: Load) -> Double? {
        get {
            assert(indexIsValid(row: row.rawValue, col: col.rawValue), "Index out of range")
            return array[(row.rawValue * cols) + col.rawValue]
        }
        set {
            assert(indexIsValid(row: row.rawValue, col: col.rawValue), "Index out of range")
            array[(row.rawValue * cols) + col.rawValue] = newValue
        }
    }
}

var timingRetard = TimingRetard2D.init(rows: 3, cols: 3, repeating: nil)
timingRetard[.cool, .idle] = 0.0
timingRetard[.cool, .cruise] = 0.0
timingRetard[.cool, .wot] = 0.0
timingRetard[.above_range, .wot] = -8.0
timingRetard[.normal, .cruise] = 0.0
print(timingRetard.array)

OUTPUT: OUTPUT:

[Optional(0.0), Optional(0.0), Optional(0.0), nil, Optional(0.0), nil, nil, nil, Optional(-8.0)] [可选(0.0),可选(0.0),可选(0.0),无,可选(0.0),无,无,无,可选(-8.0)]

Minor update to Puneet's solution, which allows the array of arrays instead of calculating offsets into a single dimensional array: 对Puneet解决方案的次要更新,该解决方案允许使用数组数组而不是将偏移量计算为一维数组:

enum ECT: Int{
    case cool = 0
    case normal
    case above_range
}

enum Load: Int {
    case idle = 0
    case cruise
    case wot
}

struct TimingRetard2D {
    let rows: Int, cols: Int
    private(set) var array:[[Double?]]

    init(rows: Int, cols: Int, repeating:Double?) {
        self.rows = rows
        self.cols = cols
        let initRow = Array(repeating: repeating, count: cols)
        array = Array(repeating: initRow, count: rows)
    }

    private func indexIsValid(row: Int, col: Int) -> Bool {
        return row >= 0 && row < rows && col >= 0 && col < cols
    }

    subscript(row: ECT, col: Load) -> Double? {
        get {
            assert(indexIsValid(row: row.rawValue, col: col.rawValue), "Index out of range")
            return array[row.rawValue][col.rawValue]
        }
        set {
            assert(indexIsValid(row: row.rawValue, col: col.rawValue), "Index out of range")
            array[row.rawValue][col.rawValue] = newValue
        }
    }
}

var timingRetard = TimingRetard2D.init(rows: 3, cols: 3, repeating: nil)
timingRetard[.cool, .idle] = 0.0
timingRetard[.cool, .cruise] = 0.0
timingRetard[.cool, .wot] = 0.0
timingRetard[.above_range, .wot] = -8.0
timingRetard[.normal, .cruise] = 0.0
print(timingRetard.array)

However is there also away to make the consumer of the struct to also use 2D array syntax? 但是,还有没有其他方法可以使结构的使用者也使用2D数组语法? eg timingRetards[.cool][.wot] 例如TimingRetards [.cool] [。wot]

You can write something like this: 您可以这样写:

extension Array where Element == Double? {
    subscript(load: Load) -> Element {
        get {
            return self[load.rawValue]
        }
        set {
            self[load.rawValue] = newValue
        }
    }
}

extension Array where Element == [Double?] {
    subscript(ect: ECT) -> Element {
        get {
            return self[ect.rawValue]
        }
        set {
            self[ect.rawValue] = newValue
        }
    }
}


var timingRetard = [[Double?]](repeating: [nil,nil,nil], count: 3)

timingRetard[.cool][.idle] = 0.0
timingRetard[.cool][.cruise] = 0.0
timingRetard[.cool][.wot] = 0.0
timingRetard[.above_range][.wot] = -8.0
timingRetard[.normal][.cruise] = 0.0

But, it seems better to extend your TimingRetard2D . 但是,最好扩展TimingRetard2D

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM