仅基于 X 在数组中查找 cgpoint

Finding cgpoint in array based only on X

我在 Swift 中有一个 CGPoints 数组。

我想仅使用 X 值在数组中找到一个点(它们都有唯一的 X 值,所以这应该不是问题),然后从中获取 Y 值。

我还想要一种方法来仅查看它是否包含具有我正在寻找的 X 值的点,例如只关心 X 的 .contains。

您可以使用 indexOf: 函数通过谓词查找数组中某项的索引。从那里,您可以使用索引访问该项目。

这实际上回答了你的两个问题,因为它要么是 returns 带有你的 X 值的 CGPoint 的索引,要么是 returns nil.

let index = pointArray.indexOf {
    [=10=].x == xToFind
}

if let index = index {
    let point = pointArray[index]
    // Do something with the point that has the x-value you wanted
} else {
    // There is no point in the array with the x-value you wanted
}

处理此类问题的一种过于复杂但很好的方法是使用协议和扩展。

如果我们创建一个 XYType protocol,它具有 typealias Elementx 以及 y 类型的 Element 属性,我们可以扩展SequenceType封装了filtercontains方法。

protocol XYType {

    typealias Element

    var x : Element { get set }
    var y : Element { get set }

}

extension CGPoint : XYType {} 

现在是真正的方法:

扩展 SequenceType 但使用约束。 Generator.Element 应该是 XYTypeGenerator.Element.ElementXYTypeElement)应该是 Equatable.

实际的过滤函数有点复杂。但本质上它使用它获得的函数作为参数 includeElement: (Self.Generator.Element.Element) throws -> Bool 并且如果它是真的它附加到一个副本。到底它returns那个copy.

extension SequenceType where Generator.Element : XYType, Generator.Element.Element : Equatable {

    // this function just mimics the regular filter.
    func filterByX(@noescape includeElement: (Self.Generator.Element.Element) throws -> Bool) rethrows -> [Self.Generator.Element] {

        var copy : [Generator.Element] = []

        for element in self where try includeElement(element.x) {

            do {
                let include = try includeElement(element.x)
                if include {
                    copy.append(element)
                }
            } catch {
                continue
            }
        }

        return copy
    }

    func filterByY(@noescape includeElement: (Self.Generator.Element.Element) throws -> Bool) rethrows -> [Self.Generator.Element] {

        var copy : [Generator.Element] = []

        for element in self where try includeElement(element.y) {

            do {
                let include = try includeElement(element.y)
                if include {
                    copy.append(element)
                }
            } catch {
                continue
            }
        }

        return copy
    }
}

contains

做同样的事情
extension SequenceType where Generator.Element : XYType, Generator.Element.Element : Equatable {


    func containsX(@noescape predicate: (Self.Generator.Element.Element) throws -> Bool) rethrows -> Bool {

        for element in self {
            do {
                let result = try predicate(element.x)
                if result {
                    return true
                }
            } catch {
                continue
            }
        }

        return false
    }

    func containsY(@noescape predicate: (Self.Generator.Element.Element) throws -> Bool) rethrows -> Bool {

        for element in self {
            do {
                let result = try predicate(element.y)
                if result {
                    return true
                }
            } catch {
                continue
            }
        }

        return false
    }

}

测试:

let points = [CGPoint(x: 1, y: 1),CGPoint(x: 2, y: 2),CGPoint(x: 3, y: 3),CGPoint(x: 4, y: 4)]

// CGPoint(2,2)
points.filterByY { (y) -> Bool in
    y == 2
}

// false
points.containsX { (x) -> Bool in
    x == 5
}

P.S。 :

你也可以这样做,它有点短:

let filtered = points.filter {
    [=14=].x == 2
}

let contains = points.contains {
    [=14=].x == 3
}