How to check if an element is in an array

后端 未结 17 968
囚心锁ツ
囚心锁ツ 2020-11-22 10:24

In Swift, how can I check if an element exists in an array? Xcode does not have any suggestions for contain, include, or has, and a qu

17条回答
  •  不思量自难忘°
    2020-11-22 10:51

    (Swift 3)

    Check if an element exists in an array (fulfilling some criteria), and if so, proceed working with the first such element

    If the intent is:

    1. To check whether an element exist in an array (/fulfils some boolean criteria, not necessarily equality testing),
    2. And if so, proceed and work with the first such element,

    Then an alternative to contains(_:) as blueprinted Sequence is to first(where:) of Sequence:

    let elements = [1, 2, 3, 4, 5]
    
    if let firstSuchElement = elements.first(where: { $0 == 4 }) {
        print(firstSuchElement) // 4
        // ...
    }
    

    In this contrived example, its usage might seem silly, but it's very useful if querying arrays of non-fundamental element types for existence of any elements fulfilling some condition. E.g.

    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.
    

    Any chained operations using .filter { ... some condition }.first can favourably be replaced with first(where:). The latter shows intent better, and have performance advantages over possible non-lazy appliances of .filter, as these will pass the full array prior to extracting the (possible) first element passing the filter.


    Check if an element exists in an array (fulfilling some criteria), and if so, remove the first such element

    A comment below queries:

    How can I remove the firstSuchElement from the array?

    A similar use case to the one above is to remove the first element that fulfils a given predicate. To do so, the index(where:) method of Collection (which is readily available to array collection) may be used to find the index of the first element fulfilling the predicate, whereafter the index can be used with the remove(at:) method of Array to (possible; given that it exists) remove that 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"]
    }
    

    Or, if you'd like to remove the element from the array and work with, apply Optional:s map(_:) method to conditionally (for .some(...) return from index(where:)) use the result from index(where:) to remove and capture the removed element from the array (within an optional binding clause).

    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
    }
    

    Note that in the contrived example above the array members are simple value types (String instances), so using a predicate to find a given member is somewhat over-kill, as we might simply test for equality using the simpler index(of:) method as shown in @DogCoffee's answer. If applying the find-and-remove approach above to the Person example, however, using index(where:) with a predicate is appropriate (since we no longer test for equality but for fulfilling a supplied predicate).

提交回复
热议问题