В Swift, как я могу проверить, существует ли элемент в массиве? У Xcode нет предложений для contain
, include
или has
, и быстрый поиск в книге ничего не показал. Любая идея, как проверить это? Я знаю, что существует метод find
, который возвращает номер индекса, но есть ли метод, который возвращает логическое значение типа ruby #include?
?
Пример того, что мне нужно:
var elements = [1,2,3,4,5]
if elements.contains(5) {
//do something
}
Swift 2, 3, 4:
let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}
contains()
- это метод расширения протокола SequenceType
(для последовательностей элементов Equatable
), а не глобальный метод, как в
более ранние версии.
Примечания:
contains()
требует, чтобы элементы последовательности
принять протокол Equatable
, сравнить, например, Эндрюс отвечает.NSObject
то вам нужно переопределить isEqual:
, см. подкласс NSObject в Swift: hash vs hashValue, isEqual vs ==.contains()
метод, который не требует, чтобы элементы были равномерными и принимали предикат как
аргумент, см., например, Сокращение, чтобы проверить, существует ли объект в массиве для Swift?.Быстрые версии:
let elements = [1,2,3,4,5]
if contains(elements, 5) {
println("yes")
}
Для тех, кто пришел сюда, ищет поиск и удаляет объект из массива:
Swift 1
if let index = find(itemList, item) {
itemList.removeAtIndex(index)
}
Swift 2
if let index = itemList.indexOf(item) {
itemList.removeAtIndex(index)
}
Swift 3, 4
if let index = itemList.index(of: item) {
itemList.remove(at: index)
}
Используйте это расширение:
extension Array {
func contains<T where T : Equatable>(obj: T) -> Bool {
return self.filter({$0 as? T == obj}).count > 0
}
}
Использовать как:
array.contains(1)
Обновлено для Swift 2/3
Обратите внимание, что с Swift 3 (или даже 2) расширение больше не требуется, поскольку глобальная функция contains
была сделана в пару метода расширения на Array
, что позволяет вам выполнить одно из следующих действий:
let a = [ 1, 2, 3, 4 ]
a.contains(2) // => true, only usable if Element : Equatable
a.contains { $0 < 1 } // => false
Если вы проверяете, содержится ли экземпляр настраиваемого класса или структуры в массиве, перед тем как вы сможете использовать протокол Equatable. содержит (MyObject).
Например:
struct Cup: Equatable {
let filled:Bool
}
static func ==(lhs:Cup, rhs:Cup) -> Bool { // Implement Equatable
return lhs.filled == rhs.filled
}
то вы можете сделать:
cupArray.contains(myCup)
Совет: переопределение == должно находиться на глобальном уровне, а не внутри вашего класса/структуры
Я использовал фильтр.
let results = elements.filter { el in el == 5 }
if results.count > 0 {
// any matching items are in results
} else {
// not found
}
Если вы хотите, вы можете сжать это, чтобы
if elements.filter({ el in el == 5 }).count > 0 {
}
Надеюсь, что это поможет.
Обновление для Swift 2
Ура для реализаций по умолчанию!
if elements.contains(5) {
// any matching items are in results
} else {
// not found
}
{$0 == 5}
...
(Swift 3)
Если это намерение:
Затем альтернативой contains(_:)
, поскольку синий текст Sequence
соответствует first(where:)
Sequence
:
let elements = [1, 2, 3, 4, 5]
if let firstSuchElement = elements.first(where: { $0 == 4 }) {
print(firstSuchElement) // 4
// ...
}
В этом надуманном примере его использование может показаться глупым, но это очень полезно, если запрашивать массивы не фундаментальных типов элементов для существования каких-либо элементов, выполняющих какое-либо условие. Например.
struct Person {
let age: Int
let name: String
init(_ age: Int, _ name: String) {
self.age = age
self.name = name
}
}
let persons = [Person(17, "Fred"), Person(16, "Susan"),
Person(19, "Hannah"), Person(18, "Sarah"),
Person(23, "Sam"), Person(18, "Jane")]
if let eligableDriver = persons.first(where: { $0.age >= 18 }) {
print("\(eligableDriver.name) can possibly drive the rental car in Sweden.")
// ...
} // Hannah can possibly drive the rental car in Sweden.
let daniel = Person(18, "Daniel")
if let sameAgeAsDaniel = persons.first(where: { $0.age == daniel.age }) {
print("\(sameAgeAsDaniel.name) is the same age as \(daniel.name).")
// ...
} // Sarah is the same age as Daniel.
Любые цепные операции с использованием .filter { ... some condition }.first
могут быть заменены на first(where:)
. Последний показывает намерение лучше и имеет преимущества производительности по сравнению с возможными нелазными устройствами .filter
, поскольку они передадут полный массив до извлечения (возможного) первого элемента, передающего фильтр.
Комментарий ниже запросов:
Как удалить
firstSuchElement
из массива?
Аналогичный вариант использования приведенного выше - удалить первый элемент, который выполняет заданный предикат. Для этого index(where:)
метод Collection
(который легко доступен для коллекции массива) можно использовать для поиска индекса первого элемента, выполняющего предикат, после чего индекс можно использовать с remove(at:)
метод Array
to (возможно, если он существует) удаляет этот элемент.
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let indexOfFirstSuchElement = elements.index(where: { $0 == "c" }) {
elements.remove(at: indexOfFirstSuchElement)
print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}
Или, если вы хотите удалить элемент из массива и работать с ним, примените Optional
: s map(_:)
метод для условно (для .some(...)
return from index(where:)
) используйте результат из index(where:)
, чтобы удалить и захватить удаленный элемент из массива (в необязательном предложении привязки).
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let firstSuchElement = elements.index(where: { $0 == "c" })
.map({ elements.remove(at: $0) }) {
// if we enter here, the first such element have now been
// remove from the array
print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
// and we may work with it
print(firstSuchElement) // c
}
Обратите внимание, что в надуманном примере выше элементы массива представляют собой простые типы значений (String
экземпляры), поэтому использование предиката для поиска данного члена несколько завышено, поскольку мы можем просто проверить равенство, используя более простой index(of:)
, как показано в @DogCoffee answer. Однако, применяя подход find-and-remove выше к примеру Person
, использование index(where:)
с предикатом является подходящим (поскольку мы больше не проверяем равенство, а выполняем поставленный предикат).
С Swift 2.1 NSArrays имеют containsObject
, которые можно использовать так:
if myArray.containsObject(objectImCheckingFor){
//myArray has the objectImCheckingFor
}
Самый простой способ сделать это - использовать фильтр в массиве.
let result = elements.filter { $0==5 }
result
будет иметь найденный элемент, если он существует и будет пустым, если элемент не существует. Поэтому, просто проверяя, является ли result
пустым, вы узнаете, существует ли элемент в массиве. Я бы использовал следующее:
if result.isEmpty {
// element does not exist in array
} else {
// element exists
}
let result = elements.filter { $0==5 }.first
должен выполнить то, что вы ищете.
На всякий случай кто-то пытается найти, если indexPath
находится среди выбранных (например, в функциях UICollectionView
или UITableView
cellForItemAtIndexPath
):
var isSelectedItem = false
if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
if contains(selectedIndexPaths, indexPath) {
isSelectedItem = true
}
}
Вот мое небольшое расширение, которое я только что написал, чтобы проверить, содержит ли мой массив делегатов объект-делегат или нет (Swift 2).:) Он также работает с типами значений, такими как шарм.
extension Array
{
func containsObject(object: Any) -> Bool
{
if let anObject: AnyObject = object as? AnyObject
{
for obj in self
{
if let anObj: AnyObject = obj as? AnyObject
{
if anObj === anObject { return true }
}
}
}
return false
}
}
Если у вас есть идея, как оптимизировать этот код, чем просто дайте мне знать.
Swift
Если вы не используете объект, вы можете использовать этот код для пользователя.
let elements = [ 10, 20, 30, 40, 50]
if elements.contains(50) {
print("true")
}
Если вы используете NSObject Class в swift. Эти переменные соответствуют моим требованиям. вы можете изменить свое требование.
var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!
Это для одного и того же типа данных.
{ $0.user_id == cliectScreenSelectedObject.user_id }
Если вы хотите тип AnyObject.
{ "\($0.user_id)" == "\(cliectScreenSelectedObject.user_id)" }
Полное условие
if cliectScreenSelected.contains( { $0.user_id == cliectScreenSelectedObject.user_id } ) == false {
cliectScreenSelected.append(cliectScreenSelectedObject)
print("Object Added")
} else {
print("Object already exists")
}
если пользователь найдет определенные элементы массива, используйте ниже код так же, как целочисленное значение.
var arrelemnts = ["sachin", "test", "test1", "test3"]
if arrelemnts.contains("test"){
print("found") }else{
print("not found") }
if find(elements, 5) != nil { }
недостаточно хорош?