user9043410
user9043410

Reputation:

swift find the 2nd and 3rd lowest numbers in an array -

Below I have a list of cities and I compare a user's current location to the cities and use the (min) function

let closestCity = min(theDistanceInMetersFromBusselton,theDistanceInMetersFromBunbury,theDistanceInMetersFromJoondalup,theDistanceInMetersFromArmadale)

to return the closest city, though now I would like to return the second and third closest city.

I haven't been able to get this to work as yet though I'm thinking something along the lines of:

citiesArray - closestCity = SecondClosestCitiesArray 

then do a secondClosestCity = min(SecondClosestCitiesArray) to get the second closest city.

Then repeat this to find the third closest?

Any ideas?

extension HomePage {
    func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
    {
        let db = Firestore.firestore()

        guard let uid = Auth.auth().currentUser?.uid else { return }

        let location = locations[0]
        let actualLatitude = String(location.coordinate.latitude)
        let actualLongitude = String(location.coordinate.longitude)

        guard let doubleActualLatitude = Double(actualLatitude) else { return }

        guard let doubleActualLongitude = Double(actualLongitude) else { return }

        ///users current location
        let usersCurrentLocation = CLLocation(latitude: doubleActualLatitude, longitude: doubleActualLongitude)

        //////////////list of locations ////////////////

        //////////ARMADALE/////////////////////

        let ArmadaleLatitude = Double(-32.1530)
        let ArmadaleLongitude = Double(116.0150)

        let ArmadaleCoordinates = CLLocation(latitude:ArmadaleLatitude, longitude: ArmadaleLongitude)

        let theDistanceInMetersFromArmadale = usersCurrentLocation.distance(from: ArmadaleCoordinates)

        ////////////////Bunbury///////////////////
        let BunburyLatitude = Double(-33.3256)
        let BunburyLongitude = Double(115.6396)

        let BunburyCoordinates = CLLocation(latitude:BunburyLatitude, longitude: BunburyLongitude)

        let theDistanceInMetersFromBunbury = usersCurrentLocation.distance(from: BunburyCoordinates)

        /////////////////////////////////////////////

        ////////Busselton//////////////////
        let busseltonLatitude = Double(-33.6555)
        let busseltonLongitude = Double(115.3500)

        let busseltonCoordinates = CLLocation(latitude:busseltonLatitude, longitude: busseltonLongitude)

        let theDistanceInMetersFromBusselton = usersCurrentLocation.distance(from: busseltonCoordinates)
        /////////////////////////////////

        /////////Joondalup////////////////////
        let JoondalupLatitude = Double(-32.5361)
        let JoondalupLongitude = Double(115.7424)

        let JoondalupCoordinates = CLLocation(latitude:JoondalupLatitude, longitude: JoondalupLongitude)

        let theDistanceInMetersFromJoondalup = usersCurrentLocation.distance(from: JoondalupCoordinates)

        //////////////////////////////////////

        /////return the the closest city
        let closestCity = min(theDistanceInMetersFromBusselton,theDistanceInMetersFromBunbury,theDistanceInMetersFromJoondalup,theDistanceInMetersFromArmadale)

        func findClosestCity(){
            //////////Armadale////////////////////////
            if closestCity == theDistanceInMetersFromArmadale{
                db.collection("Users").document(uid).setData(["Location": "Armadale" ], options: SetOptions.merge())

            /////////Bunbury////////////
            }else if closestCity == theDistanceInMetersFromBunbury{
                let Bunbury = "Bunbury"

                db.collection("Users").document(uid).setData(["Location": Bunbury ], options: SetOptions.merge())

            ///////////// Busselton//////////////
            }else if closestCity == theDistanceInMetersFromBusselton{
                let Busselton = "Busselton"

                db.collection("Users").document(uid).setData(["Location": Busselton ], options: SetOptions.merge())

            /////////////Joondalup//////////////////
            }else if closestCity == theDistanceInMetersFromJoondalup{
                db.collection("Users").document(uid).setData(["Location": "Joondalup" ], options: SetOptions.merge())
            }
        }
    }
}

Upvotes: 0

Views: 377

Answers (2)

Callam
Callam

Reputation: 11539

let cityLocations = [
    "Armadale": CLLocation(latitude: -32.1530, longitude: 116.0150),
    "Bunbury": CLLocation(latitude: -33.3256, longitude: 115.6396),
    "Busselton": CLLocation(latitude: -33.6555, longitude: 115.3500),
    "Joondalup": CLLocation(latitude: -32.5361, longitude: 115.7424)
]

func distanceFromCity(_ city: String, location: CLLocation) -> Double? {
    return cityLocations[city].flatMap { location.distance(from: $0) }
}

func citiesClosestToLocation(_ location: CLLocation, n: Int) -> [String] {
    let cities = cityLocations.sorted {
        location.distance(from: $0.value) < location.distance(from: $1.value)
    }
    return cities.dropLast(cities.count - n).map({ $0.key })
}

let testLocation = cityLocations["Armadale"]!

print(citiesClosestToLocation(testLocation, n: 3)) // ["Armadale", "Joondalup", "Bunbury"]

Upvotes: 1

deoKasuhal
deoKasuhal

Reputation: 2897

You can add these value into an array and while adding it, make sure that they are getting added to sorting order. The array at any given point will give you closest city on the first index and second closest city on the second index.

Here is an example :

extension Array where Element == Double {
    mutating func appendSorted(_ element: Double) {
        if self.count == 0 {
            self.append(element)
            return
        }
        for i in 0..<self.count {
            if element < self[i] {
                self.insert(element, at: i)
                return
            }
        }
        self.append(element)
    }
}

Upvotes: 0

Related Questions