Home > OS >  removing duplicate airport codes string in an array in swift
removing duplicate airport codes string in an array in swift

Time:01-21

I have an array of strings which are airport codes something like this,

let list = [ "JFK-ATL-CDG-JFK",
             "HKG-MIA-NRT",
             "LAX-DFW-FRA-CDG-AMS-FRA-DFW",
             "PEK-SEA-MCO-YYZ-SEA",
             "MSP-DTW-BKK"]

What I want to do is return only the strings which has duplicate airport codes, so if a user visits the same city again then I would like that string to be returned in an array like this.

let updatedList = [ "JFK-ATL-CDG-JFK",
                    "LAX-DFW-FRA-CDG-AMS-FRA-DFW",
                    "PEK-SEA-MCO-YYZ-SEA"]

Second and third element in the array does not have duplicate codes so those are not returned in the new array, Notice that airport codes are separated by "-" does Swift provide a way to remove "-" and add them back? what is the easiest way to do this. Thanks.

CodePudding user response:

you could try something simple like this, works for me:

let list = [ "JFK-ATL-CDG-JFK",
             "HKG-MIA-NRT",
             "LAX-DFW-FRA-CDG-AMS-FRA-DFW",
             "PEK-SEA-MCO-YYZ-SEA",
             "MSP-DTW-BKK"]

var updatedList: [String] = []
list.forEach { item in
    let test = item.split(separator: "-").map{String($0)}
    if test.count != Set(test).count {
        updatedList.append(item)
    }
}
print("\n---> updatedList: \(updatedList) \n")

Or, more succinctly:

let updatedList: [String] = list.map{ item in
    let arrTest = item.split(separator: "-").map{String($0)}
    return arrTest.count != Set(arrTest).count ? item : nil
}.compactMap{$0}

CodePudding user response:

Notice that airport codes are separated by "-" does Swift provide a way to remove "-" and add them back?

It's not specific to dashes (that would be silly, because what if I want to split on commas and add them back?), but yes. Here's how I would model this:

import Foundation

extension Sequence where Element: Hashable {
    func hasDuplicates() -> Bool {
        var seenElements = Set<Element>()
        return !allSatisfy { element in
            let wasSeenBefore = seenElements.insert(element).inserted
            return wasSeenBefore
        }
    }
}

struct Route {
    let airports: [String]
    
    var hasRepetions: Bool { airports.hasDuplicates() }
}

extension Route {
    init(parsingFrom input: String) {
        self.init(airports: input.components(separatedBy: "-"))
    }
    
    func encodeToString() -> String {
        airports.joined(separator: "-")
    }
}

let list = [
    "JFK-ATL-CDG-JFK",
    "HKG-MIA-NRT",
    "LAX-DFW-FRA-CDG-AMS-FRA-DFW",
    "PEK-SEA-MCO-YYZ-SEA",
    "MSP-DTW-BKK",
]

let routes = list.map(Route.init(parsingFrom:))
let routesWithRepetitions = routes.filter(\.hasRepetions)
print(routesWithRepetitions)
print(routesWithRepetitions.map { $0.encodeToString() })

I would recommend you take your input data, and at the earliest possible point in your program, parse it into a some model objects, like the Route I've shown here. This type gives a very natural place to put something like the hasRepetitions property, which you can then use to filter down your input as you need.

If you need the output at the end to be the strings again, then serialize your model objects back to string, but only do so at the last possible second. That way all your route-handling code can work in terms of handy Route objects that do useful things, instead of generic Strings.

  • Related