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
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
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) })
Thats quite easy to do. Your function which calculate the distance must take two parameter of type what is in your array you want to sort and return Bool, for example:
// I assumed your array stores MyLocation
func mySortFunc(location1: MyLocation, location2: MyLocation) -> Bool {
// do your calculation here and return true or false
}
var array: [MyLocation] = ...
array.sortInPlace { (loc1, loc2) -> Bool in
mySortFunc(loc1, location2: loc1)
}