如何获得CGPoint数组的每个值重复的次数

时间:2017-01-26 05:53:00

标签: arrays swift sorting filtering

我有一个CGPoint s数组,

pointArray = [(532.7, 150.0), (66.6, 150.0), (129.2, 150.0), (129.2, 150.0), (301.2, 150.0), (444.2, 150.0), (532.7, 150.0), (532.7, 150.0), (532.7, 150.0)]

如何获得每个点重复的次数?

3 个答案:

答案 0 :(得分:2)

正如@Alexander在评论中所说,你应该使用NSCountedSet,你可以像这样使用它:

let array = [
    CGPoint(x: 532.7, y: 150.0),
    CGPoint(x: 66.6, y: 150.0),
    CGPoint(x: 129.2, y: 150.0),
    CGPoint(x: 129.2, y: 150.0),
    CGPoint(x: 301.2, y: 150.0),
    CGPoint(x: 444.2, y: 150.0),
    CGPoint(x: 532.7, y: 150.0),
    CGPoint(x: 532.7, y: 150.0),
    CGPoint(x: 532.7, y: 150.0)
]

let countedSet = NSCountedSet(array: array)
countedSet.count(for: array.last!) //returns 4

如果您不想使用NSCountedSet,则可以将字典上的每个点存储为键,将计数存储为值。棘手的是CGPoint不符合Hashable,你可以这样做:

extension CGPoint:Hashable{
    public var hashValue: Int {
        let x = Double(self.x)
        let y = Double(self.y)

        return Int(((x + y)*(x + y + 1)/2) + y)
        //this hash function may not be the best for your data

    }
}

var map = [CGPoint:Int]()
for point in array {
    if let count = map[point] {
        map[point] = count + 1
    } else {
        map[point] = 1
    }
}

map[array.last!]//returns 4

我认为最好使用NSCountedSet

答案 1 :(得分:2)

我认为使用CountedSet太过分了。我只想算他们:

let points = [CGPoint(x: 532.7, y: 150.0), CGPoint(x: 66.6, y: 150.0), CGPoint(x: 129.2, y: 150.0), CGPoint(x: 129.2, y: 150.0), CGPoint(x: 301.2, y: 150.0), CGPoint(x: 444.2, y: 150.0), CGPoint(x: 532.7, y: 150.0), CGPoint(x: 532.7, y: 150.0), CGPoint(x: 532.7, y: 150.0)]
var d : [NSValue:Int] = [:]
for p in points {
    let v = NSValue(cgPoint:p)
    if let ct = d[v] {
        d[v] = ct+1
    } else {
        d[v] = 1
    }
}
// how many times does `points[0]` appear in `points`?
d[NSValue(cgPoint:points[0])] // 4

答案 2 :(得分:0)

我同意亚马认为,公认的解决方案看起来有点矫枉过正。我建议他采用类似的方法,但使用功能风格:

FBSDKShareLinkContent

使用这种方法,使用原始数组,我们得到如下结果:

let dictionary:[String:Int] = array.reduce([:]){
    var dict = $0.0, key = String(describing: $0.1)
    dict[key] = (dict[key] ?? 0 ) + 1
    return dict
}

请注意,使用let pointArray:[(CGFloat, CGFloat)] = [(532.7, 150.0), (66.6, 150.0), (129.2, 150.0), (129.2, 150.0), (301.2, 150.0), (444.2, 150.0), (532.7, 150.0), (532.7, 150.0), (532.7, 150.0)] let dictionary:[String:Int] = pointArray.reduce([:]){ var dict = $0.0, key = String(describing: $0.1) dict[key] = (dict[key] ?? 0 ) + 1 return dict } print(dictionary) //output is ["(129.2, 150.0)": 2, "(66.6, 150.0)": 1, "(532.7, 150.0)": 4, "(444.2, 150.0)": 1, "(301.2, 150.0)": 1] 作为字典键可以使用此示例代码中的元组,以及不一定是String(describing:)CGPoint个实例的其他变体。这将为您提供字典的Hashable密钥,而无需编写自定义代码; 然而,正如亚历山大在下面的评论中指出的那样,它不是生成Hashable值的最高效方式,并且如果您在数万个点或更多点上操作,或者经常运行此操作在循环中,使用Hashable与自定义函数从点元组生成哈希之间的差异可能很大