Получение произвольного типа из Reduce - PullRequest
0 голосов
/ 20 ноября 2018

Я делаю очень простую операцию.Я сортирую кучу мест на карте, чтобы создать вмещающий круг, например:

var maxLong: Double = -180
var maxLat: Double = -180
var minLong: Double = 180
var minLat: Double = 180

for coord in inCoordinates {
    maxLong = max(coord.longitude, maxLong)
    maxLat = max(coord.latitude, maxLat)
    minLong = min(coord.longitude, minLong)
    minLat = min(coord.latitude, minLat)
}

let nw: CLLocation = CLLocation(latitude: maxLat, longitude: minLong)
let se: CLLocation = CLLocation(latitude: minLat, longitude: maxLong)
let center = CLLocationCoordinate2D(latitude: (maxLat + minLat) / 2.0, longitude: (maxLong + minLong) / 2.0)
let radiusInMeters = abs(nw.distance(from: se)) / 2.0

return MKCircle(center: center, radius: radiusInMeters)

Довольно просто (да, я знаю о проблеме IDL, но я хочу сохранить это простым).

То, что я хотел бы знать, это то, что если бы я мог как-то свести цикл в вариант снижения, где вы бы получили что-то вроде этого:

let enclosingRect: MKMapRect = inCoordinates.magikalReduce {
    // Magic Happens Here -Queue Doug Henning GIF
}

Таким образом, возвращаемый прямоугольник содержит дистиллированные точки.

Да, я знаю, что я могу просто расширить Array (возможно с классификатором типа), чтобы сделать это с вычисляемым свойством, но такой вид поражает цель этого,Вышеупомянутое довольно эффективно, и я бы не стал добавлять накладные расходы, просто для фантазии (а это значит, что даже если бы я мог это сделать, он мог бы быть слишком неэффективным для использования).

Это скорееисследование любопытства, чем техническая необходимость.Приведенный выше код подходит для меня, и он довольно быстрый.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

Вы можете создать struct для хранения значений долготы и широты min / max, затем использовать reduce, где вы используете начальные значения для них для создания первоначального результата, а затем создаете обновленную версию struct с необходимыми min / max расчетами.

struct MinMaxCoordinates {
    let maxLong:Double
    let maxLat:Double
    let minLong:Double
    let minLat:Double
}


let minMaxCoordinates = inCoordinates.reduce(MinMaxCoordinates(maxLong: -180, maxLat: -180, minLong: 180, minLat: 180), {minMax, coord in
    return MinMaxCoordinates(maxLong: max(minMax.maxLong, coord.longitude), maxLat: max(minMax.maxLat, coord.latitude), minLong: min(minMax.minLong, coord.longitude), minLat: max(minMax.minLat, coord.latitude))
})

let nw: CLLocation = CLLocation(latitude: minMaxCoordinates.maxLat, longitude: minMaxCoordinates.minLong)
let se: CLLocation = CLLocation(latitude: minMaxCoordinates.minLat, longitude: minMaxCoordinates.maxLong)
let center = CLLocationCoordinate2D(latitude: (minMaxCoordinates.maxLat + minMaxCoordinates.minLat) / 2.0, longitude: (minMaxCoordinates.maxLong + minMaxCoordinates.minLong) / 2.0)
let radiusInMeters = abs(nw.distance(from: se)) / 2.0

return MKCircle(center: center, radius: radiusInMeters)
0 голосов
/ 20 ноября 2018

Вы имеете в виду

// calculate the enclosing rect with `reduce` and `union`, you have to create an `MKMapRect` from each coordinate
let enclosingRect = inCoordinates.reduce(MKMapRect.null) { $0.union(MKMapRect(origin: MKMapPoint($1), size: MKMapSize())) }
...