Home » Swift » How to elegantly compare tuples in Swift?

How to elegantly compare tuples in Swift?

Posted by: admin November 30, 2017 Leave a comment

Questions:

I do have 2 different tuples of type (Double, Double):

let tuple1 : (Double, Double) = (1,2)
let tuple2 : (Double, Double) = (3,4)

I want to compare their values using a simple if statement. Something like:

if (tuple1 == tuple2){
    // Do stuff
}

This throws the following error:

Could not find an overload for ‘==’ that accepts the supplied
arguments

My current solution is a function like this:

func compareTuples <T:Equatable> (tuple1:(T,T),tuple2:(T,T)) -> Bool{
    return (tuple1.0 == tuple2.0) && (tuple1.1 == tuple2.1)
}

I really dislike this solution and search for something more elegant. I already tried to write an extension but can’t make it work for tuples. Do you have a good solution for this problem?

Answers:

Try this:

func == <T:Equatable> (tuple1:(T,T),tuple2:(T,T)) -> Bool
{
   return (tuple1.0 == tuple2.0) && (tuple1.1 == tuple2.1)
}

It’s exactly the same as yours, but I called it ==. Then things like:

(1, 1) == (1, 1)

are true and

(1, 1) == (1, 2)

are false

Questions:
Answers:

I agree that this behavior is not expected, since tuples can be compared in diverse languages such as Python and Haskell, but according to the official documentation:

NOTE

Tuples are useful for temporary groups of related values. They are not
suited to the creation of complex data structures. If your data
structure is likely to persist beyond a temporary scope, model it as a
class or structure, rather than as a tuple. For more information, see
Classes and Structures.

So, this might be the Swift equivalent of “you’re holding the phone wrong,” but by current guidelines, the idiomatic way to do this is to define a Class or Struct (or even an Enum) with a Comparable implementation to provide == and related operators.

Questions:
Answers:

In swift there are tuples as we know. Tuples can be compared with each other using standard C operators. Tuples are compared with each other from LEFT to RIGHT

if (1,"death") < (3,"life") {   
     print("Life is better than death") // this is true
}

Swift only compares the integer values 1 and 3. That’s it, Swift does not compare the strings of death and life. It will only compare them when the first elements of the tuple are the same.

if (99,"life") < (99,"death") {   
     print("Life is better than death") // this is false
}

In the above case swift does not compare the integer values of 99, instead it will compare life and death. Additionally: Swift can only compare tuples which have max 6 elements. More than 6 elements you have to compare it by yourself.

Questions:
Answers:

The following approach compares tuple of any number of members of any size, provided they do not contain collection types like Array and Dictionary

import Darwin // or Foundation
/// here we go
func memeq<T>(var lhs:T, var rhs:T)->Bool {
    return withUnsafePointers(&lhs, &rhs) {
        memcmp($0, $1, UInt(sizeof(T)))
    } == 0
}

let l = (false, 42,  log(exp(1.0)))
let r = (!true, 6*7, exp(log(1.0)))
println(memeq(l, r))   // expectedly true
let l2 = (0, [0])
let r2 = (0, [0])
println(memeq(l2, r2)) // unfortunately false

Note types are already checked via generics. If they differ, it does not even compile thanks to type checking.

Leave a Reply

Your email address will not be published. Required fields are marked *