Am trying to create a 2D lookup table with enums representing the axes of the table in swift 4, for example:
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)
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? 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.
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:
[Optional(0.0), Optional(0.0), Optional(0.0), nil, Optional(0.0), nil, nil, nil, Optional(-8.0)]
Minor update to Puneet's solution, which allows the array of arrays instead of calculating offsets into a single dimensional array:
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? eg 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
.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.