(Свифт 3)
Проверьте, существует ли элемент в массиве (удовлетворяющий некоторым критериям), и если это так, продолжите работу с первым таким элементом
Если целью является:
- Чтобы проверить, существует ли элемент в массиве (/ удовлетворяет некоторым логическим критериям, не обязательно проверке на равенство),
- И если так, продолжайте и работайте с первым таким элементом,
Тогда альтернатива , contains(_:)
как blueprinted 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(...)
возврата из 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's. , Однако, если применить вышеописанный подход к поиску и удалению Person
, index(where:)
то целесообразно использовать с предикатом (поскольку мы больше не проверяем равенство, а выполняем предоставленный предикат).
if find(elements, 5) != nil { }
не достаточно хорош?