Проверка того, содержит ли массив пользовательских объектов определенный пользовательский объект

Скажем, у меня очень простой класс Person

class Person {
    var name:String
    init(name:String) {
        self.name = name
    }
}

и я хочу сохранить коллекции такого Person в свойстве, которое представляет собой массив с типом Person, класса People

class People {
    var list:[Person] = []
}

возможно, я достигаю этого следующим образом

var alex = Person(name:"Alex")
var people = People()
people.list.append(alex)

ВОПРОС: как я могу проверить, содержит ли people.list экземпляр alex?

моя простая попытка, которую я надеялся вернуть true

people.list.contains(alex)

вызывает ошибку "cannot convert value of type 'Person' to expected argument type '@noescape (Person) throws -> Bool'"

Ответы

Ответ 1

Существуют две функции contains:

extension SequenceType where Generator.Element : Equatable {
    /// Return `true` iff `element` is in `self`.
    @warn_unused_result
    public func contains(element: Self.Generator.Element) -> Bool
}

extension SequenceType {
    /// Return `true` iff an element in `self` satisfies `predicate`.
    @warn_unused_result
    public func contains(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
}

Компилятор жалуется, потому что компилятор знает, что Person не Equatable, и поэтому contains должен иметь predicate, но alex не является предикатом.

Если люди в вашем массиве Equatable (это не так), вы можете использовать:

person.list.contains(alex)

Поскольку они не являются равнозначными, вы можете использовать вторую функцию contains с помощью:

person.list.contains { $0.name == alex.name }

или, как указывает Мартин R, на основе "identity" с:

person.list.contains { $0 === alex }

или вы можете сделать Person be Equatable (на основе либо name, либо идентификатора).

Ответ 2

ВОПРОС: как я могу проверить, содержит ли people.list экземпляр alex?

class Person является ссылочным типом, а var alex является ссылкой к хранилищу объектов. Тождественный оператор === проверяет, относятся ли две константы или переменные к одному экземпляру класса.

Поэтому, чтобы проверить, содержит ли список  конкретный экземпляр, используйте предикат contains() метод и сравнить экземпляры с ===:

if people.list.contains({ $0 === alex }) {
    // ...
}