Установить пересечение неправильно - PullRequest
0 голосов
/ 18 июня 2019

Я создаю программу, которая работает с географической информацией.У меня есть данные, которые содержат, какие географические единицы касаются друг друга.Функция, которая не работает, предназначена для добавления соседних единиц в массив на основе совокупности (например, она начинается с единицы, затем добавляет наиболее массивную соседнюю единицу в массив, а затем добавляет самую густонаселенную единицу, которая касается одной из единицв массиве, и продолжает это, пока не достигнет предела населения).Я делаю это с помощью цикла 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)"
    }


}

Что не так и как я могу это исправить?Спасибо.

1 Ответ

0 голосов
/ 18 июня 2019

Проблема связана с тем, что вы удаляете элементы useBoard, одновременно перебирая useBoard. Вы печатаете индексы "\(newTemp[t]) (\(next)), ", а затем пять строк, удаляя индекс; перед повторением процесса. Хотя вы можете изменять значения коллекции, для которой вы выполняете итерацию, никогда не изменяйте размер коллекции одновременно.

Первым шагом может быть копирование useBoard перед запуском внешнего цикла. Держите его постоянным, чтобы вы перебирали все его содержимое, но использовали копию для всей своей логики. У меня проблемы с выполнением намерений вашего кода.

Что касается хеша, то не ваша проблема. Однако это не идеально. Swift предоставляет хэш по умолчанию, который почти всегда лучше. Просто позвольте Swift синтезировать свой собственный алгоритм, изменив это расширение на это.

extension Precinct: Hashable {}

Есть пара вопросов. Пожалуйста, удалите вызов для сортировки useBoard во внешнем цикле. Это не имеет никакого эффекта, потому что useBoard уже был отсортирован перед входом в цикл. Также Array(Set(superArray)) ничего не делает для вас.

Удачи.

...