0

I have an array of location coordinates like this

let coodinatesArray: [CLLocationCoordinate2D] = [
    CLLocationCoordinate2DMake(-37.986866915266461, 145.0646907496548),
    CLLocationCoordinate2DMake(-30.082868871929833, 132.65902204771416),
    CLLocationCoordinate2DMake(-21.493671405743246, 120.25335334577362),
    CLLocationCoordinate2DMake(-20.311181400000002, 118.58011809999996),
    CLLocationCoordinate2DMake(-20.311183981008153, 118.58011757850542),
    CLLocationCoordinate2DMake(-8.3154534852154622, 119.32445770062185),
    CLLocationCoordinate2DMake(4.0574731310941274, 120.06879782273836),
    CLLocationCoordinate2DMake(16.244430153007979, 120.68908125783528), 
    CLLocationCoordinate2DMake(27.722556142642798, 121.4334213799517),
    CLLocationCoordinate2DMake(37.513067999999976, 122.12041999999997)
]

I found some answers 1, 2 but I cannot use it since my array is not Equatable. Is it possible to remove it using filter in swift for arrays?

Fogmeister
  • 76,236
  • 42
  • 207
  • 306
Abin Baby
  • 586
  • 6
  • 17
  • None of the locations in this list are duplicates. How close do you want them to be to be considered "duplicate?" (Doubles provide much more precision than the GPS actually gives you.) Just making `CLLocationCoordinate2D` be `Equatable` glosses over this fact, making many "equal" coordinates appear to be different. – Rob Napier May 25 '18 at 15:21
  • The requirement to use `filter` is too restrictive. – matt May 25 '18 at 16:04

1 Answers1

5

You can create an extension to CLLocationCoordinate2D to make it conform to Hashable.

extension CLLocationCoordinate2D: Hashable {
    public var hashValue: Int {
        return Int(latitude * 1000)
    }

    static public func == (lhs: CLLocationCoordinate2D, rhs: CLLocationCoordinate2D) -> Bool {
        // Due to the precision here you may wish to use alternate comparisons
        // The following compares to less than 1/100th of a second
        // return abs(rhs.latitude - lhs.latitude) < 0.000001 && abs(rhs.longitude - lhs.longitude) < 0.000001
        return lhs.latitude == rhs.latitude && lhs.longitude == rhs.longitude
    }
}

Then you can get unique locations using Set:

let coodinatesArray: [CLLocationCoordinate2D] = ... // your array
let uniqueLocations = Array(Set(coodinatesArray))

If you need to keep the original order you can replace that last line with:

let uniqueLocations = NSOrderedSet(array: coodinatesArray).array as! [CLLocationCoordinate2D]
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • I tried this it removes duplicate value but this changes the order of locations. Is it possible to use [filter](https://developer.apple.com/documentation/swift/sequence/2905694-filter) in this array? or any other solutions which do not change the order of locations in the array? – Abin Baby May 25 '18 at 15:59
  • Don't even entertain the idea of using `==` between the location's components – Alexander May 25 '18 at 17:02