我有一个对象数组,我想找到重复项。我比较了经度/经度,不幸的是,这些数值并不完全相等。
如何找到重复项?
我的示例代码:
var locations = [("Location_A", 49.5858, 9.123456), ("Location_B", 49.5858, 9.123456), ("Location_A", 49.5855, 9.123450), ...]
for location in locations {
//Find duplicate based on longitude and latitude where values < 0.0004
}
在这种情况下,locations[0]
和locations[2]
应被视为重复。
提前致谢!
答案 0 :(得分:3)
使用自定义结构代替元组。现在你可以使该结构成为Equatable,为这个结构定义==
,以便允许你的epsilon值:
struct Loc : Equatable {
let name : String
let latitude : Double
let longitude : Double
static let epsilon = 0.0004
static func ==(lhs:Loc, rhs:Loc) -> Bool {
if lhs.name != rhs.name { return false }
if abs(lhs.latitude - rhs.latitude) > epsilon { return false }
if abs(lhs.longitude - rhs.longitude) > epsilon { return false }
return true
}
}
让我们测试一下:
let loc1 = Loc(name: "Location_A", latitude: 49.5858, longitude: 9.123456)
let loc2 = Loc(name: "Location_A", latitude: 49.5855, longitude: 9.123450)
print(loc1 == loc2) // true
在那时,用于消除重复的成熟技术将会生动起来。
答案 1 :(得分:3)
元组不易使用,我建议首先将数据包装到自定义对象中:
import CoreLocation
struct MyLocation: Hashable {
let name: String
let coordinate: CLLocation
init(tuple: (String, Double, Double)) {
name = tuple.0
coordinate = CLLocation(latitude: tuple.1, longitude: tuple.2)
}
public static func == (lhs: MyLocation, rhs: MyLocation) -> Bool {
return
lhs.name == rhs.name
&& lhs.coordinate.distance(from: rhs.coordinate) < 1
}
public var hashValue: Int {
return name.hashValue
}
}
正如您所看到的,我已经声明Equatable
和Hashable
以便于索引。
然后我们可以使用简单的Array
扩展名:
extension Array where Element: Hashable {
func distinct() -> [Element] {
var uniqueValues: Set<Element> = []
return self.filter {
let (inserted, _) = uniqueValues.insert($0)
return inserted
}
}
}
并将其用于我们的数据:
var locations = [("Location_A", 49.5858, 9.123456), ("Location_B", 49.5858, 9.123456), ("Location_A", 49.5855, 9.123450)]
let myLocations = locations
.map { MyLocation(tuple: $0) }
.distinct()
print(myLocations)
请注意,当它们距离小于1米时,我已经为两个对象定义了相等性。这比简单地将经度与经度和纬度与纬度进行比较要慢,但它也会更精确。