Pet*_*Pik 4 arrays sorting ios swift
我正在尝试按距当前位置的距离对数组进行排序。首先,您会看到organizationObject其中包含不同值的,然后我们得到的位置是一组不同位置的数组。之所以如此,array是因为一个组织可以有多个位置。然后在ViewController中,我创建了一组测试对象并将其追加到数组中。我的问题是如何orgArray根据distanceFromLocation 对此进行排序?如果位置数组中有多个位置,则应采用最接近的位置。
OrganizationObject
class OrganizationObject {
var id: Int
var name: String
var image: UIImage
var locations: [CLLocationCoordinate2D]
init(id: Int, name: String, image: UIImage, locations: [CLLocationCoordinate2D]) {
self.id = id
self.name = name
self.image = image
self.locations = locations
}
}
Run Code Online (Sandbox Code Playgroud)
将测试对象追加到数组。在viewDidLoad中
orgArray.append(OrganizationObject(id: 0, name: "Statens Museum For Kunst", image: UIImage(named: "statensmuseum.jpg")!, locations: [CLLocationCoordinate2D(latitude: 55.6888127, longitude: 12.578330300000061)]))
orgArray.append(OrganizationObject(id: 0, name: "7 eleven", image: UIImage(named: "7eleven.jpg")!, locations: [CLLocationCoordinate2D(latitude: 58.334682, longitude: 8.231820900000002)]))
orgArray.append(OrganizationObject(id: 0, name: "Kongens have", image: UIImage(named: "kongenshave.jpg")!, locations: [CLLocationCoordinate2D(latitude: 55.6852905, longitude:12.579845200000022)]))
orgArray.append(OrganizationObject(id: 0, name: "Magasin du nord", image: UIImage(named: "magasin.jpg")!, locations: [CLLocationCoordinate2D(latitude: 50.6456604, longitude: 3.053486600000042), CLLocationCoordinate2D(latitude: 55.7835017, longitude: 12.370985799999971)]))
Run Code Online (Sandbox Code Playgroud)
这是一个解决方案。这是一个更复杂一点,要排序功能的简单调用了几个原因:首先,需要找到该组织最近的位置,在问题中提到,其次是内部使用的半正矢计算的事实CLLocation的distanceFromLocation:方法如果天真地使用它会减慢速度。
由于这些原因,我创建了一个特殊的对象进行排序,因此我可以使用成员字典来记忆对的调用结果distanceFromLocation。这不会对测试数据产生影响,但是如果您需要处理大量地点,那将很重要。
附带说明-如果OrganizationObject存储CLLocation而不是-可能会使事情变得简单一些CLLocationCoordinate-尽管这是一个相当小的问题。
这是代码:
class OrganizationSorter {
var memoizedValues = [Int:CLLocationDistance]()
private func shortestDistanceToOrganizationFromLocation(organization:OrganizationObject,location:CLLocation) -> CLLocationDistance? {
let memoizedValue = memoizedValues[organization.id] //Check whether we've done this calculation before, if so return the result from last time
if memoizedValue != nil {
return memoizedValue
}
//There should probably be some code around here to check
//that the organization object has at least one location
//I'm assuming it does to simplify things
var shortestDistance : CLLocationDistance? = nil
let locations = organization.locations
if locations.count > 0 {
for coord in locations {
let loc = CLLocation(latitude: coord.latitude, longitude: coord.longitude)
let dist = loc.distanceFromLocation(location)
if shortestDistance == nil || shortestDistance > dist {
shortestDistance = dist
}
}
}
if shortestDistance != nil {
memoizedValues[organization.id] = shortestDistance
}
return shortestDistance
}
func sortOrganizationsByDistanceFromLocation(orgArray:[OrganizationObject],location:CLLocation) -> [OrganizationObject] {
let sortedArray = orgArray.sort { (a:OrganizationObject, b:OrganizationObject) -> Bool in
let dist1 = self.shortestDistanceToOrganizationFromLocation(a, location: location)
let dist2 = self.shortestDistanceToOrganizationFromLocation(b, location: location)
return dist1 < dist2
}
memoizedValues.removeAll() //reset memoized values in case object is used twice
return sortedArray
}
}
Run Code Online (Sandbox Code Playgroud)
我已经使用哥本哈根的克里斯蒂安堡宫的位置作为测试位置,对您的示例数据进行了测试,并获得了以下顺序:
Kongens have
Statens Museum For Kunst
Magasin du nord
7 eleven
Run Code Online (Sandbox Code Playgroud)
似乎与给定的坐标相匹配-看起来,最近的Magasin du Nord坐标是在哥本哈根郊区的一个城镇中的某个地方(另一个在里尔吗?),还有11个在瑞典。
这是使用类的方式(使用原始问题中的测试数据,并更改id了OrganizationObjects中的值,以使它们不全为0(否则代码将不起作用)。
let location = CLLocation(latitude: 55.676251, longitude: 12.580570) //Christiansborg Palace, chosen since it is relatively near the other locations, to make it obvious whether results are sensible or not
let orgSorter = OrganizationSorter()
let sortedLocations = orgSorter.sortOrganizationsByDistanceFromLocation(orgArray, location: location)
for org in orgArray {
print(org.name)
}
print("\n")
for org in sortedLocations {
print(org.name)
}
Run Code Online (Sandbox Code Playgroud)