How do I check if an array of tuples contains a particular one in Swift?

You can use a predicate and check for equality:

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)
}

You can also create your own contains methods that takes generic tuples:

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)
}

Add the following to your code:

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 is not that flexible when it comes to tuples. They do not conform to the Equatable protocol. So you must define that or use the above function.


While tuples aren’t Equatable, you do not need to go so far as writing your own version of contains, since there is a version of contains that takes a matching predicate:

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

While you can’t extend tuples to be equatable, you can write a version of == for tuples, which would make the above code simpler:

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

It’d be nice to be able to write a version of contains for tuples, but alas, I don’t think the placeholder syntax supports it:

EDIT: as of Swift 1.2, this does now compile as you can use tuples in placeholder constraints

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")
}