Maury Markowitz
Maury Markowitz

Reputation: 9273

Compact way to check if "dictionary item exists and is not blank" in Swift?

I'm parsing a 1970s-era text file (originally from the CDC 6600) which contains lines with variable numbers of parameters. Here are some samples...

GW 1 5 0.0000 -1.0000 0.0000000 0.00000 1.0000 0.000 .00667
GE 1
FR 0 0 0 0 46.29 0.

I am using split (yay, finally fixed in Xcode 7!) to break this down into an array, and then insert non-zero values into a dictionary, like this...

let parts: [String] = original!.characters.split{ $0 == " " || $0 == "," }.map{ String($0).trim() }
if parts.count > 1 { data["I1"] = parts[1] }
if parts.count > 2 { data["I2"] = parts[2] }
if parts.count > 3 { data["F1"] = parts[3] }

Finally, I sanity check the inputs, because I've seen many examples of incorrect files. So I have a series of functions like this...

func checkGA() {
    if (data["I1"] == "" || data["I2"] == "" || data["F1"] == "" || data["F2"] == "" || data["F3"] == "" || data["F4"] == "") { problem = "Missing parameters." }
    if (data["F5"] != "" || data["F6"] != "" || data["F7"] != "") { problem = "Extra paramters after F4." }
}

I have a feeling there might be a less ugly way to check these inputs in Swift. I was thinking that perhaps I could use the range operator in a map or similar? Something along the lines of:

if (data["F2"..."F4"] != "") ...

But this sort of functional programming is very very new to me. Any gurus have a suggestion?

Upvotes: 2

Views: 320

Answers (2)

Kateryna Gridina
Kateryna Gridina

Reputation: 844

You can create extension to dictionary:

extension Dictionary {
    func keysExistsAndNotEmpty(keysArray: [Key]) -> Bool {
        for key in keysArray {
            if (self[key] as! String).isEmpty {
                return false
            }
        }
        return true
    }
}

and after check your dictionary this way:

    let data = ["a": "a", "b": "b"]
    let keysArray = ["a", "b"] 
    if !data.keysExistsAndNotEmpty(keysArray) {
        // throw error
    }

Upvotes: 0

Tom Pelaia
Tom Pelaia

Reputation: 1285

You might consider using error handling:

enum FieldError : ErrorType {
    case MissingField(String)
    case ExtraField(String,String)
}

do {
    // sample data
    let data = ["I1": "hello", "I2": "world", "F1":"Greetings" ]

    try ["I1", "I2", "F1"].forEach { key in
        guard let value = data[key] where value != "" else {
            throw FieldError.MissingField(key)
        }
    }

    try ["F5", "F6", "F7", "F8"].forEach { key in
        if let value = data[key] where value != "" {
            throw FieldError.ExtraField(key, value)
        }
    }

    print("All data tests passed")
}
catch FieldError.MissingField(let key) {
    print("Missing field for key: \(key)")
}
catch let FieldError.ExtraField(key, value) {
    print("Extra field with key: \(key), value: \(value)")
}

Upvotes: 1

Related Questions