Search code examples
arraysswiftsearchcontains

Swift: Determine if a array of custom objects contains a particular string


I have an array called carArray which is an array of Cars.
How can I write a function to determine if the array contains a specific model? For example if a user inputs "BMW", how can I determine if that is in the array? I am trying to avoid answering this problem with writing a for loop to loop through the entire array each time this happens.

struct Car {
    var make: String?
    var model: String?
    var year: Double?
}

var carArray: [Car] = []

carArray.append(Car(make: "Audi", model: "S5", year: 2015))
carArray.append(Car(make: "BMW", model: "X3", year: 2016))
carArray.append(Car(make: "Honda", model: "Accord", year: 2018))

Solution

  • Add something like this

    func contains(make: String) -> Bool {
        carArray.compactMap(\.make).contains(make)
    } // returns true in your case for "BMW"
    

    This has two parts. First, I am mapping the array of Car objects to an array of String? by mapping over the make key path. Since this may have nil values, I am using compactMap to remove the nil values.

    If you are going to be doing this a lot and don't want the overhead of mapping and checking every time then create something to store your cars. Something like this:

    struct Car {
        var make: String?
        var model: String?
        var year: Double?
    }
    
    struct CarStore {
        private(set) var  storage: [Car] = .init()
        private var makes: Set<String> = .init()
    
        mutating func add(car: Car) {
            storage.append(car)
            car.make.map { makes.insert($0) } // map to run the closure only if make is not nil
        }
    
        func contains(make: String) -> Bool {
            makes.contains(make)
        }
    }
    
    var store = CarStore()
    
    store.add(car: Car(make: "Audi", model: "S5", year: 2015))
    store.add(car: Car(make: "BMW", model: "X3", year: 2016))
    store.add(car: Car(make: "Honda", model: "Accord", year: 2018))
    
    store.contains(make: "BMW") // -> true