Home > Net >  Loop through Struct to check a value
Loop through Struct to check a value

Time:04-27

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
    }
}
  • Related