Reputation: 8664
I'm trying to have a dictionary that have Strings as key and array of String as value.
Then I want to check if 2 of those dictionaries are equal like so:
let dicOfStringStringAr1: [String : [String]] = ["key1" : ["val", "for key 1"]]
let dicOfStringStringAr2: [String : [String]] = ["key1" : ["val", "for key 1"]]
if dicOfStringStringAr1 == dicOfStringStringAr2 {
print("Dictionary of String Array")
}
But I get this error:
error: binary operator '==' cannot be applied to two '[String : [String]]' operands
But if the values are String instead of [String] it works.
let dicOfStringAr1: [String : String] = ["key1" : "val"]
let dicOfStringAr2: [String : String] = ["key1" : "val"]
if dicOfStringAr1 == dicOfStringAr2 {
print("Dictionary of String Array")
}
I don't understand the problem.
Someone can explain what is the issue.
After looking at the default == Swift function for Dictionary
@warn_unused_result
public func ==<Key : Equatable, Value : Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool
I realized that there is no definition where Value is represented as an array, and that the "generic" Value can't be resolve to a collection. (Not sure why).
So I made a == function that would have [Key : [Value]] parameters. And now the code work.
@warn_unused_result
public func ==<Key : Equatable, Value : Equatable>(lhs: [Key : [Value]], rhs: [Key : [Value]]) -> Bool {
var result = lhs.count == rhs.count
for (k, v) in lhs {
guard let arValue = rhs[k] where result == true else {
result = false
break
}
result = v == arValue
}
return result
}
Can someone explain why in the Swift == implementation Value can't be resolve to a single item, being an array?
Upvotes: 1
Views: 1331
Reputation: 1236
It actually makes sense. As you can see from the ==
function for type <Key : Equatable, Value : Equatable>
, it requires Value
to conform Equatable
. By default, Array
type doesn't conform to Equatable
. Note, this doesn't mean you cannot compare two arrays using ==
.
[1, 2, 3] == ["a", "b", "c"] // false.
Conforming to Equatable
means you can use ==
but not vice verse.
You can of course extend the Array
type to conform to Equatable
.
extension Array: Equatable {}
// Implement the following method.
public func ==<T: CollectionType, U: CollectionType>(lhs: T, rhs: U) -> Bool {}
Update
I would say it's not possible right now to implement a plausible ==
for Array
. (It might be possible in the future swift version)
For your specific case, I would say the following method is fair enough. When you have a custom struct
, just make sure it conforms Equatable
.
public func ==<Key : Equatable, Value : CollectionType where Value.Generator.Element: Equatable>(lhs: [Key : Value], rhs: [Key : Value]) -> Bool {
guard lhs.keys.elementsEqual(rhs.keys) else { return false }
for (key, value) in lhs {
if !value.elementsEqual(rhs[key]!) { return false }
}
return true
}
Example would be:
struct Number: Equatable {
var x: Int
var y: Int
}
func ==(lhs: Number, rhs: Number) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
let dicOfStringStringAr1: [String : [Number]] = ["key1" : [Number(x: 1, y: 2), Number(x: 1, y: 2)]]
let dicOfStringStringAr2: [String : [Number]] = ["key1" : [Number(x: 1, y: 2), Number(x: 1, y: 2)]]
if dicOfStringStringAr1 == dicOfStringStringAr2 {
print("Dictionary of String Array") // "Dictionary of String Array"
}
Upvotes: 1
Reputation: 2035
Fortunately, you can check if these dictionaries are equal by converting your dictionary to a NSDictionary and using its method isEqualToDictionary
. For example:
if NSDictionary(dictionary: dicOfStringStringAr1).isEqualToDictionary(dicOfStringStringAr2) {
print("Dictionary of String Array")
}
Upvotes: 0