Swift tuples are not Equatable, and as compound types, they can't be made Equatable through protocol extension. The workaround (as documented in another answer) is to create an overload for the ==
operator for each arity of tuples.
Interestingly, one can declare the ==
operator for regular tuples and use it to compare tuples with named fields:
func ==<T1: Equatable, T2: Equatable>(lhs: (T1,T2), rhs: (T1,T2)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
var one = ("One", 1)
let two = ("Two", 2)
print(one == two) // "false"
typealias NamedTuple2 = (name: String, value: Int)
var namedone: NamedTuple2 = (name: "One", value: 1)
let namedtwo: NamedTuple2 = (name: "Two", value: 2)
print(namedone == namedtwo) // "false"
print(namedone == one) // "true"
Arrays of tuples also need a custom overload to be compared as a whole:
func ==<T0: Equatable, T1: Equatable>(lhs: [(T0, T1)], rhs: [(T0, T1)]) -> Bool {
if lhs.count != rhs.count {
return false
}
for (index, value) in lhs.enumerate() {
if !(value == rhs[index]) {
return false
}
}
return true
}
let array12: [(String, Int)] = [one, two]
let array3: [Tuple2] = [("Three", 3)]
print(array12 == array3) // "false"
However, this operator doesn't accept an array of named tuples:
let namedarray12: [NamedTuple2] = [namedone, namedtwo]
let namedarray3: [NamedTuple2] = [array3[0]]
print(namedarray12 == namedarray3)
// error: binary operator '==' cannot be applied to two '[NamedTuple2]' operands
Is there a way to test equality of arrays of named tuple, without declaring an overload of ==
for the particular named tuple?
To compare tuples, just use the == operator, like this: let singer = ("Taylor", "Swift") let alien = ("Justin", "Bieber") if singer == alien { print("Matching tuples!") } else { print("Non-matching tuples!") }
Suggested approach: Swift provides automatic tuple comparison ever since Swift 2.2 – you can just use == to compare tuples item by item. For bonus points you could mention that tuple comparison does not guarantee that both tuples use the same element names.
The rule is simple: if all of the tuple elements are themselves Equatable then the overall tuple itself conforms to Equatable . It's also important to note that this conformance does not take into account the tuple labels in consideration for equality.
Tuple A tuple is a grouping of unnamed, ordered values. Each value in a tuple does not need to be the same type. Array An array is mutable collection. They are very efficient to create, but must always be a single type.
The method SequenceType.elementsEqual(_,isEquivalent:)
accepts a predicate for comparing elements. The same ==
overload works for both named and unnamed tuples. So instead of trying to apply ==
to the arrays as a whole, use elementsEqual
.
func ==<T1: Equatable, T2: Equatable>(lhs: (T1,T2), rhs: (T1,T2)) -> Bool {
return lhs.0 == rhs.0 && lhs.1 == rhs.1
}
let namedarray: [(name: String, value: Int)] = [(name: "One", value: 1), (name: "Two", value: 2)]
// namedarray == namedarray12
namedarray.elementsEqual(namedarray12, isEquivalent: ==) // true
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With