按距离当前位置排序数组

时间:2015-09-21 19:06:46

标签: ios arrays swift sorting

我试图按距离当前位置的距离对数组进行排序。首先,您会看到organizationObject,其中包含不同的值,然后我们的位置是不同位置的数组。它是array的原因是因为组织可以有多个位置。然后在我的ViewController中创建一组测试对象并附加到数组。我的问题是如何根据distanceFromLocation对orgArray进行排序?如果位置数组中有多个位置,则应采用最接近的位置。

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
    }

}

将测试对象附加到数组。在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)]))

1 个答案:

答案 0 :(得分:5)

这是一个解决方案。由于以下几个原因,直接调用排序函数会稍微复杂一些:首先需要找到组织中最近的位置,如问题中所提到的,其次是在{{1}内使用的半正式计算这一事实如果天真地使用,CLLocation方法会减慢速度。

出于这些原因,我创建了一个特殊对象来进行排序,这样我就可以使用成员字典来memoize调用distanceFromLocation:的结果。这不会对测试数据产生影响,但如果您需要处理大量的地方,这将很重要。

作为旁注 - 如果distanceFromLocation存储OrganizationObject而不是CLLocation,则可能会使事情变得更简单一点 - 尽管这是一个相当小的问题。

以下是代码:

CLLocationCoordinate

我已根据您的示例数据对其进行了测试,使用哥本哈根Christiansborg Palace的位置作为测试位置,并按以下顺序进行测试:

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
  }
}

似乎与给定的坐标相匹配 - 看起来像Magasin du Nord最近的坐标是在哥本哈根郊区的一个小镇的某个地方(另一个在里尔?),而且11个在瑞典。 / p>

以下是如何使用类(使用原始问题中的测试数据,Kongens have Statens Museum For Kunst Magasin du nord 7 eleven 中的id值已更改,因此它们不是全0(否则代码将无法正常工作) )。

OrganizationObject