【问题标题】:How do I check if an array of tuples contains a particular one in Swift?如何检查元组数组是否包含 Swift 中的特定元组?
【发布时间】:2015-06-26 11:47:32
【问题描述】:

考虑以下 Swift 代码。

var a = [(1, 1)]

if contains(a, (1, 2)) {
    println("Yes")
}

我只需要检查a 是否包含元组,但代码会导致错误。

找不到接受参数列表的“包含”的重载 类型为'([(Int, Int)], (Int, Int))'

为什么会这样以及如何正确使用contains

【问题讨论】:

    标签: arrays swift tuples


    【解决方案1】:

    您可以使用谓词并检查是否相等:

    let tuples = [(1, 1), (0, 1)]
    
    let tuple1 = (1, 2)
    let tuple2 = (0, 1)
    
    if tuples.contains(where: {$0 == tuple1}) {
        print(true)
    } else {
        print(false)    // false
    }
    
    if tuples.contains(where: {$0 == tuple2}) {
        print(true)    // true
    } else {
        print(false)
    }
    

    您还可以创建自己的包含通用元组的方法:

    extension Sequence  {
        func contains<T, U>(_ tuple: (T, U)) -> Bool where T: Equatable, U: Equatable, Element == (T,U) {
            contains { $0 == tuple }
        }
        func contains<T, U, V>(_ tuple: (T, U, V)) -> Bool where T: Equatable, U: Equatable, V: Equatable, Element == (T,U,V) {
            contains { $0 == tuple }
        }
        func contains<T, U, V, W>(_ tuple: (T, U, V, W)) -> Bool where T: Equatable, U: Equatable, V: Equatable, W: Equatable,Element == (T, U, V, W) {
            contains { $0 == tuple }
        }
        func contains<T, U, V, W, X>(_ tuple: (T, U, V, W, X)) -> Bool where T: Equatable, U: Equatable, V: Equatable, W: Equatable, X: Equatable, Element == (T, U, V, W, X) {
            contains { $0 == tuple }
        }
        func contains<T, U, V, W, X, Y>(_ tuple: (T, U, V, W, X, Y)) -> Bool where T: Equatable, U: Equatable, V: Equatable, W: Equatable, X: Equatable, Y: Equatable, Element == (T, U, V, W, X, Y) {
            contains { $0 == tuple }
        }
    }
    

    if tuples.contains(tuple1) {
        print(true)
    } else {
        print(false)    // false
    }
    
    if tuples.contains(tuple2) {
        print(true)    // true
    } else {
        print(false)
    }
    

    【讨论】:

    • 我喜欢函数式编程,但我对它持怀疑态度,因为它可能会由于创建额外的集合而降低性能。所以我通常更喜欢迭代。
    • 这看起来很优雅。一个缺点是,对于(非常)大的数组,它必须遍历整个数组才能最终找出第一个已经匹配的数组,这将是浪费时间......
    • @JayForeman 只要集合中的对象是不可变的,就不会影响性能。如果 Swift 发现包含的对象是不可变的,它就不会创建新的集合。
    【解决方案2】:

    虽然元组不是Equatable,但您无需编写自己的contains 版本,因为contains 的版本需要匹配谓词:

    if contains(a, { $0.0 == 1 && $0.1 == 2 }) {
         // a contained (1,2)
    }
    

    虽然您不能将元组扩展为可相等的,但您可以为元组编写一个 == 的版本,这将使上述代码更简单:

    func ==<T: Equatable, U: Equatable>(lhs: (T,U), rhs: (T,U)) -> Bool {
        return lhs.0 == rhs.0 && lhs.1 == rhs.1
    }
    
    contains(a) { $0 == (1,2) } // returns true
    

    如果能够为元组编写contains 的版本,那将是不错,但是我不认为占位符语法支持它:

    编辑:从 Swift 1.2 开始,现在可以编译,因为您可以在占位符约束中使用元组

    func contains
      <S: SequenceType, T: Equatable, U: Equatable where S.Generator.Element == (T,U)>
      (seq: S, x: (T,U)) -> Bool {
        return contains(seq) { $0.0 == x.0 && $0.1 == x.1 }
    }
    
    let a = [(1,1), (1,2)]
    
    if contains(a, (1,2)) {
        println("Yes")
    }
    

    【讨论】:

    • @AirspeedVelocity - 您能否发布“func contains
    • @AirspeedVelocity - 如果可能,请检查以下代码在 Swift 3.0 中是否正确转换 ... Start ... func TupleContains (seq: S , x: (T,U)) -> Bool where S.Iterator.Element == (T,U) { return seq.contains(where: { $0.0 == x.0 && $0.1 == x.1 }) }
    【解决方案3】:

    将以下内容添加到您的代码中:

    func contains(a:[(Int, Int)], v:(Int,Int)) -> Bool {
      let (c1, c2) = v
      for (v1, v2) in a { if v1 == c1 && v2 == c2 { return true } }
      return false
    }
    

    Swift 在元组方面没有那么灵活。它们不符合Equatable 协议。所以你必须定义它或使用上面的函数。

    【讨论】:

    • 元组不是Equatable 听起来很奇怪,而且不能使用== 来检查两个元组是否相等。
    • @Jay Tuples 作为一个整体不可能是Equatable,因为它们可能包含不相等的类型。选项和数组也是如此,它们可以(并且确实)也有==,但不是Equatable。元组具有额外的复杂性,即无法编写适用于 2 元组、3 元组、n 元组等的通用代码,因此没有为它们定义默认的 ==
    【解决方案4】:

    您不能使用contains 方法解决您的问题。 Swift 中也没有嵌入式解决方案。所以你需要自己解决这个问题。 您可以创建一个简单的函数来检查数组中的元组是否与要检查的元组相同:

    func checkTuple(tupleToCheck:(Int, Int), theTupleArray:[(Int, Int)]) -> Bool{
        //Iterate over your Array of tuples
        for arrayObject in theTupleArray{
            //If a tuple is the same as your tuple to check, it returns true and ends
            if arrayObject.0 == tupleToCheck.1 && arrayObject.1 == tupleToCheck.1 {
                return true
            }
        }
    
        //If no tuple matches, it returns false
        return false
    }
    

    【讨论】:

      【解决方案5】:

      这个问题可能太老了,希望有人能得到更多选择的帮助。

      您可以使用switch 代替if 条件

          var somePoint = [(0, 1), (1, 0), (0, 0), (-2, 2)]
          for innerSomePoint in somePoint {
              switch innerSomePoint {
              case (0, 0):
                  print("\(innerSomePoint) first and second static")
              case (_, 0):
                  print("\(innerSomePoint) first dynamic second static")
              case (0, _):
                  print("\(innerSomePoint) first static second dynamic")
              case (-2...2, -2...2):
                  print("\(innerSomePoint) both in between values")
              default:
                  print("\(innerSomePoint) Nothing found")
              }
          }
      

      Also have some more option to do check here from apple doc

          somePoint = [(1, 1), (1, -1), (0, 0), (-2, 2)]
          for innerSomePoint in somePoint {
              switch innerSomePoint {
              case let (x, y) where x == y:
                  print("(\(x), \(y)) is on the line x == y")
              case let (x, y) where x == -y:
                  print("(\(x), \(y)) is on the line x == -y")
              case let (x, y):
                  print("(\(x), \(y)) is just some arbitrary point")
              }
          }
      

      【讨论】:

        【解决方案6】:

        斯威夫特 4

        将您的代码更改为:

        var a = [(1, 1)]
        
        if a.contains(where: { $0 == (1, 2) } ) {
            print("Yes")
        }
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2020-07-15
          • 1970-01-01
          • 2016-10-13
          • 2013-07-29
          • 2021-05-03
          • 2019-12-01
          • 2015-06-24
          • 2017-11-24
          相关资源
          最近更新 更多