Ios 从CGPoints数组中获取最大值和最小值

Ios 从CGPoints数组中获取最大值和最小值,ios,arrays,swift,cgpoint,Ios,Arrays,Swift,Cgpoint,我们有一组CGPoints: let points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)] 我要做的是得到数组中x值最高的CGPoint和y值最高的CGPoint。我将使用这些点创建CGRect: extension CGRect { init(p1: CGPoint, p2: CGPoint) { self.init(x: min(p1.x, p2.x), y

我们有一组CGPoints:

let points = [(1234.0, 1053.0), (1241.0, 1111.0), (1152.0, 1043.0)]
我要做的是得到数组中x值最高的CGPoint和y值最高的CGPoint。我将使用这些点创建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()
但这些似乎不起作用,因为它是一系列CG点。是否可以从数组中获取这些值?

您可以使用
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)
让minXPoint=points.min(by:{$0.x<$1.x})/(1152.01043.0)
设maxYPoint=points.max(by:{$0.y<$1.y})/(1241.01111.0)

您不能只调用
min()
/
max()

在y和x坐标的最高和最低位置

具有最小x值的点可能与具有最小x值的点不同。因此,任何只返回其中一个点的方法(如
min()
/
max()
do)都是不够的

您需要对每个用户分别进行两次呼叫,如:

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
我可能会这样做:


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)

扩展CGRect{
静态func minimarect(包含点:[CGPoint])->CGRect{
if points.isEmpty{返回nil}
设minX=points.min(by:{$0.x<$1.x})!.x
设minY=points.min(by:{$0.y<$1.y})!.y
设maxX=points.min(by:{$0.x>$1.x})!.x
设maxY=points.min(by:{$0.y>$1.y})!.y
返回CGRect(
x:minX,
y:米尼,
宽度:(minX-maxX).大小,
高度:(最小-最大)。大小
)
}
}
让点=[(1234.01053.0),(1241.01111.0),(1152.01043.0)].map(CGPoint.init)
设r=CGRect.minimalRect(包含:点)
打印(r°.zero)/=>(1152.0、1043.0、89.0、68.0)

您可以映射值以查找x和y坐标中的最小值和最大值,如下所示。如果不确定
数组是否包含任何数据,请使用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)
然后,您可以修改扩展函数,因为您已经知道哪些值是最小值和最大值:

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在下面的评论中所建议的那样,您可以在可失败的初始值设定项扩展中一次完成所有操作:

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

CGPoint
不具有可比性,因为
pointA
的含义并不明显。你想创建一个包含所有
点的最小矩形吗?@Alexander,我想创建一个基于y和x坐标的最高和最低点的CGRect,所以是的,差不多一个shapeI真的很喜欢这个答案。对于问题中提到的
,它是有效的,但是如果minX的点与minY的点不一样呢?然后它将返回minXPoint,而minY也没有。为什么不使用易出错的初始值设定项而不是静态方法呢?我对这两个方法进行了反复讨论,但在本例中,我没有使用初始值设定项,因为我想在名称中使用“rect”一词。我喜欢callsite
CGRect.minimarect(包含:点)
CGRect(minimarectcontaining:points)
points或
CGRect(minimalContaining:points)
没有必要使用闭包
map(\.x)
map(\.y)
并保留对它们的引用,而不是映射两次。您还可以将它们移动到初始化方法中,使其易于出错。谢谢@LeoDabus。我根据你的建议更新了我的答案。
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
        }
    }
}