Here is what I'm trying to do but simplified down:
var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []
var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]
for (key, val) in newdic{
for arr in adictionary[key]{
if !(adictionary[arr].contains(key)){
newdic[key] = true
}
}
}
I get these errors, when I run the above simplified version of the code I am trying to run in an ios app:
main.swift:12:28: error: value of optional type '[String]?' must be unwrapped to a value of type '[String]' for arr in adictionary[key]{
main.swift:12:28: note: coalesce using '??' to provide a default when the optional value contains 'nil' for arr in adictionary[key]{
main.swift:12:28: note: force-unwrap using '!' to abort execution if the optional value contains 'nil' for arr in adictionary[key]{
I don't understand, what is wrong with what I am doing? What do these errors mean? It seems like Swift thinks I have an optional somewhere? But I don't see how I do... Any help is much appreciated.
If I change this line: for arr in adictionary[key]{
To: for arr in adictionary[key]!{
It fixes the issues and new errors appear on the if !(a... line. I still don't understand why that fixed it.
Swift dictionary accesses always return optional values, because the lookup will return nil
if the key doesn't exist. It is up to you to handle this resulting optional is a safe way. Adding !
is rarely the right way to fix it because your code will crash if nil
is returned.
The first time you get an optional is here:
for arr in adictionary[key] {
Again, Swift doesn't know if key
exists in adictionary
so it returns an optional. A safe way to fix this is to use the dictionary lookup which returns a default
value when the key doesn't exist. In this case, returning an empty array seems like a good choice since your for
loop will then just do nothing:
for arr in adictionary[key, default:[]] {
Next, you get an optional here:
if !(adictionary[arr].contains(key)){
Again, you need to decide how to safely handle the fact that dictionary[arr]
could return nil
. The same trick works here: return an empty array if arr
doesn't exist:
if !(adictionary[arr, default:[]].contains(key)){
Here is the final version of your code:
var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []
var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]
print(newdic)
for key in newdic.keys {
for arr in adictionary[key, default:[]] {
if !(adictionary[arr, default:[]].contains(key)){
newdic[key] = true
}
}
}