Today, playing “No. Yes.”

No.

// So I have a [String: [String]]
// Is there a way to do this without the force unwrapping?
if let _ = result[key] {
    result[key]!.append(decodedValue!)
} else {
    result[key] = [decodedValue!]
}

Yes.

if let decodedValue = decodedValue {
    result[key, default: []].append(decodedValue)
}

Commentary

Dictionaries now support default values (SE-0165 and SE-0154), but even if they didn’t, you could still use nil-coalescing without introducing the check on result’s lookup:

// a [String] type for the rhs is inferred by context
result[key] ?? []

The decodedValue should be handled through with either guard-let for early exit or if-let to unwrap then use. Since this kind of code often appears in loops, if may be the better choice, allowing each optional value to be tested and added.

If you are looping, consider applying a flatMap compactMap to your source array or using for case let, enabling you to unwrap and select your input:

for value in decodedValues.compactMap({ $0 }) { 
    result[key, default: []].append(value) 
}

for case let value? in decodedValues { 
    result[key, default: []].append(value) 
}

The two approaches are not significantly different, although I tend to lean towards the latter. It involves a single pass and I think it’s more elegant.

Comments are closed.