Проблемная часть c состоит в том, чтобы выполнять итерацию по массиву и обновлять этот массив одновременно. В этом случае удаление элемента во время итерации.
Удаление элемента уменьшает длину массива (count
), а также меняет индексы. Поэтому в
for j in i + 1 ..< array.count {
if array[i] == array[j] {
newArray.remove(at: j)
}
}
После удаления первого индекса остальные ваши индексы становятся недействительными. Обратите внимание, что count
всегда читается только один раз, до фактической итерации.
Это одна из причин, по которой удаление элементов во время итерации опасно и сложно. Вы можете исправить это, сохранив количество удаленных элементов и соответственно обновив индексы. Или вы можете выполнить итерацию в обратном направлении:
var newArray = array
for i in (0 ..< newArray.count - 1).reversed() {
for j in (i + 1 ..< newArray.count).reversed() {
if newArray[i] == newArray[j] {
newArray.remove(at: j)
}
}
}
return newArray
Вы по-прежнему меняете индексы и count
, но, поскольку вы выполняете итерацию в обратном направлении, вы изменяете только те индексы, которые уже были использованы.
В целом проще и безопаснее создать новый массив вместо обновления текущего:
var newArray: [Int] = []
for value in array {
if !newArray.contains(value) {
newArray.append(value)
}
}
return newArray
, который может быть значительно уменьшен по сложности (производительности) при использовании Set
для хранения добавленных элементов:
var newArray: [Int] = []
var foundElements: Set<Int> = []
for value in array {
if foundElements.insert(value).inserted {
newArray.append(value)
}
}
return newArray
Что можно упростить с помощью filter
:
var foundElements: Set<Int> = []
return array.filter { foundElements.insert($0).inserted }