Массив [Любой] и содержит ()
Я пытаюсь проверить, если массив типа [Any]
содержит значение определенного типа (скажем, Int
).
Я знаю, что Свифт не знает, как сравнить Int
и значение произвольного типа, и я думаю, это то, что выражается в шаблоне автозаполнения:
contains(predicate: (protocol<>) throws -> Bool)
Итак, я попробовал этот код:
let intValue:Int = 5 // for example
let isContained = myArrayOfAny.contains({ element in
return ((element as? Int) == intValue)
})
... и он компилируется (пока не могу убедиться, что он работает); но до сих пор не может сделать головы или хвосты predicate: (protocol<>)
часть. Что это значит? Документация для SequenceType
довольно загадочно
contains(_: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
Default Implementation
Return true iff an element in self satisfies predicate.
Declaration
@warn_unused_result func contains(@noescape _ predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Bool
РЕДАКТИРОВАТЬ: я довольно смущен, потому что все результаты поиска, которые я видел, имеют contains()
метод Array
как просто взятие значения, которое будет проверено на сдерживание, например:
if myArrayOfInt.contains(someInt){
...
а не закрытие.
1 ответ
Есть два разных contains()
методы (оба расширения протокола для SequenceType
). Первый
extension SequenceType where Generator.Element : Equatable {
/// Return `true` iff `element` is in `self`.
@warn_unused_result
public func contains(element: Self.Generator.Element) -> Bool
}
и это требует, чтобы элементы последовательности соответствовали Equatable
протокол, который гарантирует, что их можно сравнить с ==
:
public protocol Equatable {
// ...
public func ==(lhs: Self, rhs: Self) -> Bool
}
Например, в
let intValue:Int = 5
let myArrayOfInt = [4, 5, 6]
let isContained = myArrayOfInt.contains(intValue)
у вас есть массив Int
, а также Int
соответствует Equatable
так вот contains()
Метод может быть использован для проверки наличия определенного элемента.
Это не работает для
let myArrayOfAny : [Any] = [4, 5, 6]
так как Any
не соответствует Equatable
, Здесь вы можете использовать второй contains()
метод
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
}
который принимает предикат, то есть булеву функцию. Вместо того, чтобы сравнивать с ==
предикат применяется к каждому элементу массива. Этот метод не требует, чтобы элементы массива Equatable
,
И это то, что вы делаете в
let myArrayOfAny : [Any] = [4, 5, 6]
let intValue:Int = 5 // for example
let isContained = myArrayOfAny.contains({ element in
return ((element as? Int) == intValue)
})
Это даст true
если любой элемент массива может быть приведен к Int
и равен данному intValue
,
Возможно, первый метод встречается чаще, а второй гораздо более общий, например,
if myArrayOfCustomObjects.contains ({ $0.someProperty == "foo" })
или же
if myArrayOfInts.contains ({ $0 > 17 })
Итак, первый contains()
является своего рода специализацией второй для простой проверки локализации в массивах уравниваемых элементов. Это может быть реализовано как
extension SequenceType where Generator.Element : Equatable {
public func contains(element: Self.Generator.Element) -> Bool {
return self.contains({ $0 == element } )
}
}
Вы найдете то же самое с indexOf()
который также поставляется в двух вариантах:
extension CollectionType where Generator.Element : Equatable {
// ...
public func indexOf(element: Self.Generator.Element) -> Self.Index?
}
extension CollectionType {
// ...
public func indexOf(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Index?
}