(Swift 3)
Sprawdź, czy element istnieje w tablicy (spełniając pewne kryteria), a jeśli tak, kontynuuj pracę z pierwszym takim elementem
Jeśli celem jest:
- Aby sprawdzić, czy element istnieje w tablicy (/ spełnia pewne kryteria boolowskie, niekoniecznie testowanie równości),
- A jeśli tak, kontynuuj i pracuj z pierwszym takim elementem,
Wtedy alternatywą contains(_:)
jako blueprinted Sequence
jest first(where:)
od Sequence
:
let elements = [1, 2, 3, 4, 5]
if let firstSuchElement = elements.first(where: { $0 == 4 }) {
print(firstSuchElement) // 4
// ...
}
W tym wymyślonym przykładzie jego użycie może wydawać się głupie, ale jest to bardzo przydatne, jeśli zapytanie o tablice nie fundamentalnych typów elementów o istnienie dowolnego elementu spełniającego jakiś warunek. Na przykład
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.
Wszelkie powiązane operacje przy użyciu .filter { ... some condition }.first
można korzystnie zastąpić first(where:)
. Ta ostatnia pokazuje zamiar lepiej i ma przewagę wydajności w stosunku do możliwych nie leniwych urządzeń .filter
, ponieważ przejdą one pełną tablicę przed wyodrębnieniem (możliwego) pierwszego elementu przechodzącego przez filtr.
Sprawdź, czy element istnieje w tablicy (spełniając pewne kryteria), a jeśli tak, usuń pierwszy taki element
Komentarz poniżej zapytań:
Jak mogę usunąć firstSuchElement
tablicę?
Podobny przypadek zastosowania do powyższego dotyczy usunięcia pierwszego elementu, który spełnia dany predykat. Aby to zrobić, można zastosować index(where:)
metodę Collection
(która jest łatwo dostępna w kolekcji tablic) w celu znalezienia indeksu pierwszego elementu spełniającego predykat, po czym indeks można zastosować za pomocą remove(at:)
metody Array
to (możliwe; pod warunkiem, że istnieje) usuń ten element.
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"]
}
Lub, jeśli chcesz usunąć element z tablicy i pracować z nim , zastosuj metodę Optional
: s map(_:)
, aby warunkowo (do .some(...)
zwrotu z index(where:)
) użyć wyniku z index(where:)
do usunięcia i przechwycenia usuniętego elementu z tablicy (w ramach opcjonalnej klauzuli wiążącej) .
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
}
Zauważ, że w powyższym skonstruowanym przykładzie elementy tablicy są prostymi typami wartości ( String
instancjami), więc użycie predykatu w celu znalezienia danego elementu jest nieco przesadzone , ponieważ możemy po prostu przetestować równość przy użyciu prostszej index(of:)
metody, jak pokazano w odpowiedzi @ DogCoffee . Person
Jednak w przypadku zastosowania powyższego przykładu w znajdowaniu i usuwaniu index(where:)
właściwe jest używanie z predykatem (ponieważ nie testujemy już równości, ale spełniamy podany predykat).
if find(elements, 5) != nil { }
nie jest wystarczająco dobry?