Reputation: 1017
I am trying to understand generics better and am writing a function, that finds a key in a given dictionary with a given value. If the value is not found it should return nil.
func findKey<Key, Value: Equatable>(for value: Value, in dictionary: [Key: Value]) -> Key {
for set in dictionary {
if set.value == value {
return set.key
}
}
return nil //ERROR: Nil is incompatible with Type 'Key'
}
I reveice this error:
Nil is incompatible with Type 'Key'
Upvotes: 1
Views: 550
Reputation: 63264
Alternative implementation:
extension Dictionary where Value: Equatable {
func key(forValue v: Value) -> Key? {
return self.first(where: { $0.value == v})?.key
}
}
["a": 1, "b": 2, "c": 3].key(forValue: 3) // => Optional("c")
Note that in the case where two Key
s map to the same Value
v
, it's not deterministic which of the two Key
s will be returned. To get all Key
s mapping the Value
v
, you can do this:
extension Dictionary where Value: Equatable {
func keys(forValue v: Value) -> [Key] {
return self.filter{ $0.value == v}.map{ $0.key }
}
}
["a": 1, "b": 2, "c": 3, "d": 3].keys(forValue: 3) // => ["d", "c"]
Upvotes: 1
Reputation: 855
In order to return nil you need to return a Key Optional " Key?
"
You can read more about optionals here.
func findKey<Key, Value: Equatable>(for value: Value, in dictionary: [Key: Value]) -> Key? {
for set in dictionary {
if set.value == value {
return set.key
}
}
return nil
}
Upvotes: 2
Reputation: 25261
Your function is set to return a Key
as indicated by -> Key
You cannot return a nil because Key
is an unwrapped variable. Instead, you can set the function to return an Optional
which means that it can either have a Key
, or it can be nil. Simply add a ?
after the return type
func findKey<Key, Value: Equatable>(for value: Value, in dictionary: [Key: Value]) -> Key? {
for set in dictionary {
if set.value == value {
return set.key
}
}
return nil
}
Upvotes: 2