Как проверить, находится ли элемент в массиве

333

В Swift, как я могу проверить, существует ли элемент в массиве? У Xcode нет предложений для contain, include или has, и быстрый поиск в книге ничего не показал. Любая идея, как проверить это? Я знаю, что существует метод find, который возвращает номер индекса, но есть ли метод, который возвращает логическое значение типа ruby ​​#include??

Пример того, что мне нужно:

var elements = [1,2,3,4,5]
if elements.contains(5) {
  //do something
}
  • 10
    if find(elements, 5) != nil { } недостаточно хорош?
  • 1
    Я надеялся на что-то более чистое, но это не выглядит хорошо. Я ничего не нашел ни в документации, ни в книге.
Теги:
arrays

12 ответов

663
Лучший ответ

Swift 2, 3, 4:

let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
    print("yes")
}

contains() - это метод расширения протокола SequenceType (для последовательностей элементов Equatable), а не глобальный метод, как в более ранние версии.

Примечания:

Быстрые версии:

let elements = [1,2,3,4,5]
if contains(elements, 5) {
    println("yes")
}
  • 4
    Любая документация об этом типе глобальных функций?
  • 3
    Должно ли это работать, если каждый элемент в массиве (и элемент, который мы ищем) имеет тип Dictionary <String, AnyObject>? Пытаясь добиться этого, но я получаю ошибку во время компиляции.
Показать ещё 2 комментария
94

Для тех, кто пришел сюда, ищет поиск и удаляет объект из массива:

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

Используйте это расширение:

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
  • 10
    найти быстрее.
  • 1
    в зависимости от того, к чему вы привыкли, .contains может показаться более интуитивным и запоминающимся
Показать ещё 2 комментария
29

Если вы проверяете, содержится ли экземпляр настраиваемого класса или структуры в массиве, перед тем как вы сможете использовать протокол 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)

Совет: переопределение == должно находиться на глобальном уровне, а не внутри вашего класса/структуры

22

Я использовал фильтр.

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
}
  • 12
    Или {$0 == 5} ...
  • 0
    Мне нравится решение фильтра, потому что вы можете использовать его для всех видов вещей. Например, я переносил некоторый код, который зацикливался и зацикливался, пытаясь увидеть, есть ли в списке уже элемент с одним из его полей, содержащих строковое значение. Это одна строка в Swift, использующая фильтр в этом поле.
Показать ещё 1 комментарий
8

(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:) с предикатом является подходящим (поскольку мы больше не проверяем равенство, а выполняем поставленный предикат).

  • 0
    Как я могу удалить firstSuchElement из массива?
  • 0
    @ i6x86 спасибо за вопрос. Я обновил свой ответ примером того, как удалить элемент (а также как удалить и зафиксировать удаленный элемент).
6

С Swift 2.1 NSArrays имеют containsObject, которые можно использовать так:

if myArray.containsObject(objectImCheckingFor){
    //myArray has the objectImCheckingFor
}
  • 4
    На самом деле это для NSArray. Не быстрый массив
  • 0
    Да, но вы можете временно преобразовать ваш swift-массив в NSArray: если разрешить tempNSArrayForChecking = mySwiftArray в качестве NSArray? где tempNSArrayForChecking.containsObject (objectImCheckingFor) {// myArray имеет объект}
Показать ещё 1 комментарий
6

Самый простой способ сделать это - использовать фильтр в массиве.

let result = elements.filter { $0==5 }

result будет иметь найденный элемент, если он существует и будет пустым, если элемент не существует. Поэтому, просто проверяя, является ли result пустым, вы узнаете, существует ли элемент в массиве. Я бы использовал следующее:

if result.isEmpty {
    // element does not exist in array
} else {
    // element exists
}
  • 0
    отличное решение. поэтому этот метод возвращает массив. Тем не менее, я использую это, чтобы найти «id». В моем приложении d уникальны, поэтому может быть только один результат. Есть ли способ вернуть только 1 результат? Я сейчас использую результат [0]
  • 3
    @DanBeaulieu Делая что-то вроде let result = elements.filter { $0==5 }.first должен выполнить то, что вы ищете.
3

На всякий случай кто-то пытается найти, если indexPath находится среди выбранных (например, в функциях UICollectionView или UITableView cellForItemAtIndexPath):

    var isSelectedItem = false
    if let selectedIndexPaths = collectionView.indexPathsForSelectedItems() as? [NSIndexPath]{
        if contains(selectedIndexPaths, indexPath) {
            isSelectedItem = true
        }
    }
2

Вот мое небольшое расширение, которое я только что написал, чтобы проверить, содержит ли мой массив делегатов объект-делегат или нет (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
    }
}

Если у вас есть идея, как оптимизировать этот код, чем просто дайте мне знать.

1

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

 }
0

если пользователь найдет определенные элементы массива, используйте ниже код так же, как целочисленное значение.

var arrelemnts = ["sachin", "test", "test1", "test3"]

 if arrelemnts.contains("test"){
    print("found")   }else{
    print("not found")   }

Ещё вопросы

Сообщество Overcoder
Наверх
Меню