从reduce获取任意类型

时间:2018-11-20 18:57:27

标签: swift algorithm mapkit reduce

我正在做一个非常简单的操作。我正在对地图中的一堆位置进行排序,以创建一个封闭的圆圈,如下所示:

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问题,但是我想保持简单)。

我想知道的是,是否有某种方法可以将循环构建为reduce的变体,最终您将得到如下结果:

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

所以返回的rect包含蒸馏点。

是的,我知道我可以简单地扩展Array(可能带有类型限定符)以使用计算所得的属性来完成此操作,但是这样做有悖于此目的。上面的代码相当有效,我不想增加开销,只是为了花哨(这意味着,即使我可以做到,使用起来也可能效率太低)。

这更多是出于好奇的探索,而不是技术上的需求。上面的代码对我来说很好,并且相对简单。

2 个答案:

答案 0 :(得分:2)

你是说

// 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())) }

答案 1 :(得分:1)

您可以创建一个struct来保存最小/最大经度和纬度值,然后使用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)