如何优雅地比较Swift中的元组?

时间:2014-06-30 09:59:56

标签: comparison swift tuples

我有2个不同类型的元组(Double,Double):

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

我想使用简单的if语句比较它们​​的值。类似的东西:

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

这会引发以下错误:

  

无法找到' =='接受提供的   参数

我目前的解决方案是这样的功能:

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

我真的不喜欢这个解决方案,并寻找更优雅的东西。我已经尝试编写扩展但不能使其适用于元组。你有解决这个问题的好方法吗?

6 个答案:

答案 0 :(得分:20)

试试这个:

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

它与你的完全相同,但我称之为==。然后是:

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

是真的

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

是假的

答案 1 :(得分:11)

我同意这种行为是不可取的,因为元组可以用不同的语言比较,比如Python和Haskell,但是according to the official documentation

  

请注意

     

元组对临时的相关值组很有用。他们不是   适合创建复杂的数据结构。如果你的数据   结构可能会持续超出临时范围,将其建模为一个   类或结构,而不是元组。有关更多信息,请参阅   类和结构。

所以,这可能是Swift相当于&#34;你手机错了,&#34;但根据当前的指导原则,这样做的惯用方法是使用Comparable实现来定义Class或Struct(甚至是Enum),以提供==和相关的运算符。

答案 2 :(得分:2)

在swift中,我们知道有元组。可以使用标准C运算符将元组相互比较。元组从左到右相互比较

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

Swift只比较整数值1和3.这就是它,Swift不会比较死亡和生命的字符串。它只会在元组的第一个元素相同时进行比较。

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

在上述情况下,swift不会比较99的整数值,而是比较生与死。另外:Swift只能比较最多6个元素的元组。超过6个元素你必须自己比较。

答案 3 :(得分:2)

Swift 4支持元组比较。您不会再收到错误。

这段代码可以完美运行

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

if (tuple1 == tuple2) {
    print("equal")
}
else {
    print("unequal")
}

在这里,操场的控制台上印有不相等的字样。

苹果文档中提到的元组比较的一个限制是-

  

Swift标准库包含用于以下内容的元组比较运算符   少于七个元素的元组。比较具有七个或七个的元组   更多元素,则必须自己实现比较运算符。

答案 4 :(得分:1)

类似于@JeremyP的答案,但更通用:

func ==<T1: Equatable, T2: Equatable>(lhs: (T1, T2), rhs: (T1, T2)) -> Bool {
    return lhs.0 == rhs.0 && lhs.1 == rhs.1
}

func ==<T1: Equatable, T2: Equatable, T3: Equatable>(lhs: (T1, T2, T3), rhs: (T1, T2, T3)) -> Bool {
    return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2
}

func ==<T1: Equatable, T2: Equatable, T3: Equatable, T4: Equatable>(lhs: (T1, T2, T3, T4), rhs: (T1, T2, T3, T4)) -> Bool {
    return lhs.0 == rhs.0 && lhs.1 == rhs.1 && lhs.2 == rhs.2 && lhs.3 == rhs.3
}

答案 5 :(得分:0)

以下方法比较任意大小的任意数量成员的元组,前提是它们不包含像Array和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

已通过泛型检查注释类型。如果它们不同,由于类型检查,它甚至都无法编译。