Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Sort array by calculated distance in Swift

Tags:

swift

So I have an array of custom objects which have a Double latitude and Double longitude value. I would like to sort the array based on the calculated distance from a specific point to the location for each item in the array. I have a function that will calculate the distance based on the latitude and longitude values. Is there an easy way to accomplish this sorting?

like image 508
ardevd Avatar asked Feb 04 '16 11:02

ardevd


2 Answers

Assuming you have a model Place for your objects:

class Place {
    var latitude: CLLocationDegrees
    var longitude: CLLocationDegrees

    var location: CLLocation {
        return CLLocation(latitude: self.latitude, longitude: self.longitude)
    }

    func distance(to location: CLLocation) -> CLLocationDistance {
        return location.distance(from: self.location)
    }
}

Then an array var places: [Place] can be sorted as such:

places.sort(by: { $0.distance(to: myLocation) < $1.distance(to: myLocation) })
like image 140
xoudini Avatar answered Oct 13 '22 17:10

xoudini


Another way to approach this problem is to make an extension on Array that allows you to sort by location. The benefit to this approach is that the call site is a lot cleaner and easier to understand.

** NOTE ** - I have changed the class to a struct. However this will work just fine with a class as well.

struct Place {
    var latitude: CLLocationDegrees
    var longitude: CLLocationDegrees

    var location: CLLocation {
        return CLLocation(latitude: self.latitude, longitude: self.longitude)
    }

    func distance(to location: CLLocation) -> CLLocationDistance {
        return location.distance(from: self.location)
    }
}

Then we declare an extension like so where the Element of the array is a Place:

extension Array where Element == Place {

    mutating func sort(by location: CLLocation) {
         return sort(by: { $0.distance(to: location) < $1.distance(to: location) })
    }

    func sorted(by location: CLLocation) -> [Place] {
        return sorted(by: { $0.distance(to: location) < $1.distance(to: location) })
    }
}

This allows us to then sort by location using the following syntaxes:

places.sort(by: myLocation) // mutating version

let newPlaces = places.sorted(by: myLocation) // non mutating version

like image 26
pls Avatar answered Oct 13 '22 16:10

pls