Как проверить, находится ли элемент в массиве
в Swift, как я могу проверить, существует ли элемент в массиве? Xcode не имеет никаких предложений для contain
, include
или has
, и быстрый поиск по книге ничего не обнаружил. Есть идеи, как это проверить? Я знаю, что есть метод find
это возвращает номер индекса, но есть ли метод, который возвращает логическое значение, такое как ruby's #include?
?
пример того, что мне нужно:
var elements = [1,2,3,4,5]
if elements.contains(5) {
//do something
}
14 ответов
Swift 2, 3, 4:
let elements = [1, 2, 3, 4, 5]
if elements.contains(5) {
print("yes")
}
contains()
это метод расширения протокола of SequenceType
(для последовательности Equatable
elements), а не глобальный метод, как в
предыдущие версии.
Примечания:
- этой
contains()
метод требует, чтобы элементы последовательности примитеEquatable
протокол, сравнить например ответ Эндрюса. - если последовательность элементы являются экземплярами
NSObject
подкласс тогда вы должны переопределитьisEqual:
см. подкласс NSObject в Swift: hash vs hashValue, isEqual vs ==. - есть еще один-более общий –
contains()
метод, который не требует, чтобы элементы были равнозначными и принимает предикат в качестве аргумент, см., например,Стенография, чтобы проверить, существует ли объект в массиве для Swift?.
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({ 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 { < 1 } // => false
Если вы проверяете, является ли экземпляр пользовательский класс или struct содержится в массиве, вам понадобится использовать тег 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
}
(Swift 3)
проверьте, существует ли элемент в массиве (удовлетворяющий некоторым критериям),и если да, продолжайте работать с первым таким элементом
если намерение является:
- чтобы проверить, существует ли элемент в массиве (/выполняет некоторые логические критерии, не обязательно равенство тестирования),
- и если это так, продолжайте и работайте с первым таким элементом,
затем альтернатива contains(_:)
как blueprinted Sequence
это first(where:)
of Sequence
:
let elements = [1, 2, 3, 4, 5]
if let firstSuchElement = elements.first(where: { == 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: { .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: { .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
(который легко доступен для коллекции array) может использоваться для поиска индекса первого элемента, выполняющего предикат, после чего индекс может использоваться с remove(at:)
метод Array
to (возможно; учитывая, что он существует) удалите этот элемент.
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let indexOfFirstSuchElement = elements.index(where: { == "c" }) {
elements.remove(at: indexOfFirstSuchElement)
print(elements) // ["a", "b", "d", "e", "a", "b", "c"]
}
или, если вы хотите удалить элемент из массива С применить Optional
: s map(_:)
метод условно (для .some(...)
вернуться из index(where:)
) использовать результат index(where:)
для удаления и захвата удаленного элемента из массива (в необязательном предложении binding).
var elements = ["a", "b", "c", "d", "e", "a", "b", "c"]
if let firstSuchElement = elements.index(where: { == "c" })
.map({ elements.remove(at: ) }) {
// 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
экземпляры), поэтому использование предиката для поиска данного члена несколько перебивает, так как мы может просто проверить равенство, используя simpler index(of:)
метод, как показано в @DogCoffee это. Если применить подход "найти и удалить" выше к Person
пример, однако, используя index(where:)
с предикатом подходит (так как мы больше не тестируем на равенство, а для выполнения предоставленного предиката).
самый простой способ сделать это-использовать фильтр на массиве.
let result = elements.filter { ==5 }
result
будет иметь найденный элемент, если он существует, и будет пустым, если элемент не существует. Так просто проверить, если result
is empty сообщит Вам, существует ли элемент в массиве. Я бы использовал следующее:
if result.isEmpty {
// element does not exist in array
} else {
// element exists
}
по состоянию на Swift 2.1 NSArrays имеют containsObject
Это можно использовать так:
if myArray.containsObject(objectImCheckingFor){
//myArray has the objectImCheckingFor
}
на всякий случай, если кто-то пытается найти, если 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
}
}
Если у вас есть идея, как оптимизировать этот код, просто дайте мне знать.
Свифт
если вы не используете объект, вы можете использовать этот код для contains.
let elements = [ 10, 20, 30, 40, 50]
if elements.contains(50) {
print("true")
}
если вы используете класс NSObject в swift. Эти переменные соответствуют моему требованию. вы можете доработать для вашего требования.
var cliectScreenList = [ATModelLeadInfo]()
var cliectScreenSelectedObject: ATModelLeadInfo!
Это для того же типа данных.
{ .user_id == cliectScreenSelectedObject.user_id }
если вы хотите тип AnyObject.
{ "\(.user_id)" == "\(cliectScreenSelectedObject.user_id)" }
полное условие
if cliectScreenSelected.contains( { .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") }
Swift 4, другой способ достичь этого, с функцией фильтра
var elements = [1,2,3,4,5]
if let object = elements.filter({ == 5 }).first {
print("found")
} else {
print("not found")
}
как насчет использования хэш-таблицы для работы, как это?
во-первых, создание универсальной функции "хэш-карта", расширение протокола последовательности.
extension Sequence where Element: Hashable {
func hashMap() -> [Element: Int] {
var dict: [Element: Int] = [:]
for (i, value) in self.enumerated() {
dict[value] = i
}
return dict
}
}
Это расширение будет работать столько, сколько элементов в массиве соответствует Hashable, как целые числа или строки, вот использование...
let numbers = Array(0...50)
let hashMappedNumbers = numbers.hashMap()
let numToDetect = 35
let indexOfnumToDetect = hashMappedNumbers[numToDetect] // returns the index of the item and if all the elements in the array are different, it will work to get the index of the object!
print(indexOfnumToDetect) // prints 35
но пока давайте просто сосредоточимся на проверке, находится ли элемент в массиве.
let numExists = indexOfnumToDetect != nil // if the key does not exist
means the number is not contained in the collection.
print(numExists) // prints true