(Швидкий 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
до (можливо; враховуючи, що він існує) видаліть цей елемент.
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 . Якщо застосувати підхід пошуку та видалення вище до Person
прикладу, однак, використання index(where:)
з присудком є доцільним (оскільки ми більше не перевіряємо рівність, а виконуємо доданий присудок).
if find(elements, 5) != nil { }
недостатньо добре?