The problematic part is to iterate over an array and update that array at the same time. In this case, removing an element while iterating.
Removing an element decreases array length (count) and also changes indices. Therefore in
for j in i + 1 ..< array.count {
if array[i] == array[j] {
newArray.remove(at: j)
}
}
After removing the first index, your other indices become invalid. Note that count is always read only once, before the actual iteration.
This is one of the reasons why removing elements during iteration is dangerous and complicated. You could fix it by maintaining the number of removed elements and update indices accordingly. Or you can iterate backwards:
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
You are still changing indices and count but since you are iterating backwards, you only change the indices that have been already used.
In general it's simple and safer to build a new array instead of updating the current one:
var newArray: [Int] = []
for value in array {
if !newArray.contains(value) {
newArray.append(value)
}
}
return newArray
which can be very reduced in complexity (performance) by using a Set to keep added elements:
var newArray: [Int] = []
var foundElements: Set<Int> = []
for value in array {
if foundElements.insert(value).inserted {
newArray.append(value)
}
}
return newArray
Which can be simplified using filter:
var foundElements: Set<Int> = []
return array.filter { foundElements.insert($0).inserted }
arrayand adding values in the loop instead tonewArrayfunc deleteDuplicates(array: [Int]) -> [Int] { return Array(NSOrderedSet(array: array)) as? [Int] ?? array }