PHP programer here struggling with Swift. How do I create a Struct (Mutidimentional array in PHP) and walk through the elements to check a value?
Here is the code I am trying but it fails:
struct Alert: Codable {
let begin: Double
let end: Double
let color: String
let message: String
}
var alertStack = [ Int: Alert ]()
alertStack[60] = Alert(begin: 60.0,
end: 55.0,
color: "green",
message: "60 Seconds" )
alertStack[30] = Alert(begin: 30.0,
end: 25.0,
color: "yellow",
message: "30 Seconds!")
var alrtColor = "default" // Set default
var alrtText = "" // Set default
for alrt in alertStack {
if alrt.begin <= secondsLeft {
alrtColor = alrt.color // <-- Error
alrtText = alrt.message
}
}
Error is "Value of tuple type 'Dictionary<Int, Alert>.Element' (aka '(key: Int, value: Alert)') has no member 'begin'" For a PHP guy this error message is confusing. I tried a few other things but can't seem to get the result I am looking for. I am hoping there is a simple fix or example that would work.
CodePudding user response:
You can enumerate each key value pair in a dictionary like so:
for (i, alrt) in alertStack
Where "i" would be your int value
But: it may be better to try to find a more Swifty way of expressing your problem (what are you trying to do?) rather than trying to translate from PHP. For example, perhaps like:
let alerts: [Alert] = [
(60, 55, "green", "60 Seconds"),
(30, 25, "yellow", "30 Seconds!")
]
.map(Alert.init(begin:end:color:message:))
let color: String
let alertText: String
if let foundAlert = alerts.last(where: { $0.begin < secondsLeft }) {
color = foundAlert.color
alertText = foundAlert.message
}
else {
color = "default"
alertText = ""
}
(Maybe there is a reason but I don't know why you would want to have them in a dictionary keyed by their begin numbers)
If it helps I would imagine your problem may be expressed something like this:
struct Alert: Codable {
let color: String
let message: String
static let defaultAlert = Alert(color: "default", message: "")
static let thresholds: [ClosedRange<Double>: Alert] = [
55...60: Alert(color: "green", message: "60 Seconds"),
25...30: Alert(color: "yellow", message: "30 Seconds!")
]
}
func currentAlert(value: Double) -> Alert {
// Return the alert where the range of seconds contains
// the provided remaining seconds value
guard let found = Alert.thresholds.first(where: {
$0.key.contains(value)
}) else {
return .defaultAlert
}
return found.value
}
print(currentAlert(value: 57)) // 60 Seconds
print(currentAlert(value: 42)) // default
print(currentAlert(value: 26)) // 30 Seconds!
CodePudding user response:
You're right, that's not a big deal. Everything you need to do is write alrt.value.begin, alrt.value.color and alrt.value.message. That's because of alertStack is Dictionary<Int, Alert>
(or [Int: Alert]
, it's the same) type. And alrt is element of Dictionary that always has key and value properties. In your case key is Int
, value is Alert
for alrt in alertStack {
if alrt.value.begin <= secondsLeft {
alrtColor = alrt.value.color
alrtText = alrt.value.message
}
}