簡體   English   中英

從 CGPoints 數組中獲取最大值和最小值

[英]Get the max and min values from an Array of CGPoints

我們有一個 CGPoints 數組:

let points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)]

我想要做的是獲得數組中 x 值最高的 CGPoint 和數組中 y 值最高的那個。 我將使用這些點來創建一個 CGRect:

extension CGRect {
    init(p1: CGPoint, p2: CGPoint) {
        self.init(x: min(p1.x, p2.x),
                  y: min(p1.y, p2.y),
                  width: abs(p1.x - p2.x),
                  height: abs(p1.y - p2.y))
    }
}

我知道有一種方法可以通過執行以下操作來獲取數組中的最大值和最小值:

points.min()
points.max()

但這些似乎不起作用,因為它是一組 CGPoints。 是否可以從數組中獲取這些值?

您可以使用max(by:)

let minXPoint = points.min(by: {$0.x < $1.x}) //(1152.0, 1043.0)
let maxYPoint = points.max(by: {$0.y < $1.y}) //(1241.0, 1111.0)

你不能只調用一次min() / max()

離開 y 和 x 坐標的最高點和最低點

具有最小 x 值的點可能與具有最小 x 值的點不同。 因此,任何只返回一個點的方法(如min() / max()所做的)都是不夠的。

您要么需要兩個單獨的調用,例如:

let minX = points.min(by: { $0.x < $1.x })!.x
let minY = points.min(by: { $0.y < $1.y })!.y
let maxX = points.min(by: { $0.x > $1.x })!.x
let maxY = points.min(by: { $0.y > $1.y })!.y

或者您可以嘗試使用 reduce 一口氣完成所有操作:

let initialAccumulator = (
    minX: CGFloat.max, minY: CGFloat.max, maxX: CGFloat.min, maxY: CGFloat.min)
let (minX, minY, maxX, maxY) = points.reduce(initialAccumulator) { accumulator, point in
    return (
        minX: min(accumulator.minX, point.x),
        minY: min(accumulator.minY, point.y),
        maxX: max(accumulator.maxX, point.x),
        maxY: max(accumulator.maxY, point.y)
    )
}

我可能會這樣做:


extension CGRect {
    static func minimalRect(containing points: [CGPoint]) -> CGRect? {
        if points.isEmpty { return nil }

        let minX = points.min(by: { $0.x < $1.x })!.x
        let minY = points.min(by: { $0.y < $1.y })!.y
        let maxX = points.min(by: { $0.x > $1.x })!.x
        let maxY = points.min(by: { $0.y > $1.y })!.y

        return CGRect(
            x: minX,
            y: minY,
            width: (minX - maxX).magnitude,
            height: (minY - maxY).magnitude
        )
    }
}


let points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)].map(CGPoint.init)
let r = CGRect.minimalRect(containing: points)
print(r ?? .zero) // => (1152.0, 1043.0, 89.0, 68.0)

您可以通過 map 值找到 x 和 y 坐標中的最小值和最大值,如下所示。 如果您不確定points數組是否包含任何數據,請使用 guard 語句來避免強制展開:

let xArray = points.map(\.x)
let yArray = points.map(\.y)
guard let minX = xArray.min(),
      let maxX = xArray.max(),
      let minY = yArray.min(),
      let maxY = yArray.max() else { return }

從那里:

let minPoint = CGPoint(x: minX, y: minY)
let maxPoint = CGPoint(x: minY, y: minY)

那么您可以修改您的擴展 function 因為您已經知道哪些值是最小值和最大值:

extension CGRect {
    init(minPoint: CGPoint, maxPoint: CGPoint) {
        self.init(x: minPoint.x,
                  y: minPoint.y,
                  width: maxPoint.x - minPoint.x,
                  height: maxPoint.y - minPoint.y)
    }
}

正如 Leo Dabus 在下面的評論中所建議的那樣,您可以在一個 go 內的可失敗初始化程序擴展中完成所有操作:

extension CGRect {
    init?(points: [CGPoint]) {
        let xArray = points.map(\.x)
        let yArray = points.map(\.y)
        if  let minX = xArray.min(),
            let maxX = xArray.max(),
            let minY = yArray.min(),
            let maxY = yArray.max() {

            self.init(x: minX,
                      y: minY,
                      width: maxX - minX,
                      height: maxY - minY)
        } else {
            return nil
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM