首页 > 解决方案 > 设置交点错误

问题描述

我正在创建一个处理地理信息的程序。我有包含哪些地理单位相互接触的数据。失败的函数旨在根据人口将相邻单元添加到数组中(例如,它从一个单元开始,然后将人口最多的相邻单元添加到数组中,然后添加与其中一个单元接触的人口最多的单元在数组中,并继续此操作,直到达到人口限制)。我这样做的方法是使用 for 循环,然后使用按人口排序的总单位数组。然后,我使用数组中单元的邻居与总单元数组中每个单元的邻居之间的交集找到第一个(因此也是人口最多的)邻居的索引。以下是我的代码(请原谅笨拙):

 func createDistrict () {
         if useBoard.isEmpty == false {
        useBoard.sort(by: {$0.population > $1.population})
        var maxPop = useBoard.first!.population
        district.removeAll()
        district.append(useBoard.first!)
        useBoard.removeFirst()

        for i in 0...useBoard.count - 1 {
            if useBoard.indices.contains(i) {
            if useBoard[i] == nil || district.map({$0.population}).reduce(0,+) > districtMax {
            break
            }
            } else {
                break
            }
            useBoard.sort(by: {$0.population > $1.population})
            var superArray:[Precinct] = []
            district.forEach { (z) in
                superArray += z.neighbors
                Array(Set(superArray))
            }
            var nextPre = useBoard.firstIndex { (l) -> Bool in
                Set(l.neighbors).intersection(Set(superArray)).isEmpty == false
            }
            if nextPre == nil {
                break
            }else {
                var temporary = Set(useBoard[nextPre!].neighbors).intersection(Set(superArray))
                var newString = ""
                var newTemp = Array(temporary)
                for t in 0...newTemp.count - 1 {
                    var next = useBoard.firstIndex { (k) -> Bool in
                        k == newTemp[t]
                    }
                    newString.append("\(newTemp[t]) (\(next)), ")
                }
                print("\(useBoard[nextPre!].precinctID) (\(nextPre!)) touches \(newString)")


            }

        district.append(useBoard[nextPre!])
                useBoard.remove(at: nextPre!)
        }
    }
        district.forEach { (p) in
            print("\(p.precinctID)")
        }
    }

在这个函数中,var nextPre = useBoard.firstIndex { (l) -> Bool in Set(l.neighbors).intersection(Set(superArray)).isEmpty == false}用于查找人口最多的邻居的索引。但是,当我使用 测试它时print,我得到了不正确的输出。在以下摘录中,括号中的值只是索引,并不重要。输出:

2104 (8) touches 1987 (Optional(710)), 2676 (Optional(1591)), 
2387 (10) touches 2105 (Optional(2140)), 
2274 (11) touches 2273 (Optional(52)), 2386 (Optional(236)), 
2275 (14) touches 2276 (Optional(22)), 2105 (Optional(2138)), 2273 (Optional(51)), 
2276 (21) touches 2389 (Optional(1638)), 2273 (Optional(50)), 2274 (nil), 2275 (nil), 2277 (Optional(2771)), 2386 (Optional(234)), 
2067 (35) touches 2404 (Optional(76)), 2212 (Optional(944)), 
2406 (40) touches 2404 (Optional(75)), 2070 (Optional(1771)), 
2440 (42) touches 2212 (Optional(942)), 2388 (Optional(497)), 2441 (Optional(1364)), 
2273 (46) touches 2386 (Optional(230)), 2276 (nil), 2064 (Optional(384)), 2275 (nil), 2105 (Optional(2133)), 2274 (nil), 2387 (nil), 
1795 (55) touches 1891 (Optional(1212)), 
1908 (41) touches 2638 (Optional(2568)), 1869 (Optional(474)), 
2404 (70) touches 2212 (Optional(938)), 2070 (Optional(1766)), 2069 (Optional(365)), 2068 (Optional(581)), 1743 (Optional(2453)), 2405 (Optional(2442)), 2387 (nil), 2105 (Optional(2130)), 2284 (Optional(2792)), 
2736 (70) touches 2548 (Optional(1314)), 2420 (Optional(1305)), 
1798 (52) touches 2419 (Optional(270)), 
1907 (45) touches 1912 (Optional(1611)), 2737 (Optional(2082)), 

如您所见,邻居相差 1。例如,2104 是第一个单元。然后 2387 接触 2105,即 2104 + 1。然后 2274 接触 2386,即 2387 - 1。然后 2275 接触 2105,即 2104 + 1。.intersection应该找到第一个接触数组中单元的单元,但它找到了第一个接触单位名称 + 1 的单位。我不知道这是如何发生的,因为地理单位存储在自定义对象中,而不是整数或任何其他数字变量。这是自定义对象:

class Precinct {
    var precinctID:String
    var population:Int
    var neighbors:[Precinct]
    init(precinctID:String, population:Int, neighbors:[Precinct]){
        self.precinctID = precinctID
        self.population = population
        self.neighbors = neighbors
    }
}

extension Precinct: Equatable {
    static func == (lhs: Precinct, rhs: Precinct) -> Bool {
        return lhs.precinctID == rhs.precinctID && lhs.population == rhs.population && lhs.neighbors == rhs.neighbors
    }
}

extension Precinct: Hashable {
    var hashValue: Int {
        return precinctID.hashValue ^ population.hashValue
    }
}

extension Precinct: CustomStringConvertible {
    var description: String {
        return "\(precinctID)"
    }


}

出了什么问题,我该如何解决?谢谢。

标签: arraysswiftsetintersection

解决方案


问题是由于您正在删除 useBoard 的元素,同时对 useBoard 进行迭代。您正在打印索引"\(newTemp[t]) (\(next)), ",然后在五行之后删除索引;在重复该过程之前。虽然您可以更改正在迭代的集合的值,但切勿同时更改集合的大小。

第一步可能是在运行外循环之前复制 useBoard。保持它不变,以便您迭代其所有内容,但将副本用于所有逻辑。我无法遵循您的代码的意图。

至于哈希,那不是你的问题。然而它并不理想。Swift 提供了一个几乎总是更好的默认哈希。只需将扩展名更改为 this 即可让 Swift 合成自己的算法。

extension Precinct: Hashable {}

有几个问题。请删除外循环中对 useBoard 进行排序的调用。这没有任何效果,因为 useBoard 在进入循环之前已经排序。也不Array(Set(superArray))是为你做任何事。

祝你好运。


推荐阅读