从 Swift 中的 Int 数组中删除重复项(for-in-loop)
Remove duplicates from array of Int in Swift (for-in-loop)
在 swift 中有很多方法可以从数组中删除重复项,但我正在尝试使用 for in loop 来管理它。
谁能解释一下,为什么这段代码不起作用?
Fatal error: Index out of range
func deleteDuplicates(array: [Int]) -> [Int] {
var newArray = array
for i in 0 ..< newArray.count - 1 {
for j in i + 1 ..< newArray.count {
if newArray[i] == newArray[j] {
newArray.remove(at: j)
}
}
}
return newArray
}
array1 = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
deleteDuplicates(array: array1)
一个原因是您正在修改同一个数组,您在该数组上 运行 两个 for 循环。要详细了解,请按照 Martin 所说的那样使用调试器。并且
这可以使用一个 for 循环和 Set 来完成:
var newArray = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
var array = Set<Int>()
for i in newArray {
array.insert(i)
}
print(array)
输出:
[4, 5, 3, 0, 1, 8, 6, 11, 7]
有问题的部分是遍历数组并同时更新该数组。在这种情况下,在迭代时删除一个元素。
删除元素会减少数组长度 (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([=14=]).inserted }
这是您可以尝试的一种简单方法。
func removeDuplicates(_ nums: inout [Int]) {
var arrLen = nums.count
var index = 0
while(index < arrLen - 1){
if nums[index] == nums[index+1] {
nums.remove(at: index)
arrLen = arrLen - 1
}else{
index = index+1
}
}
}
无需创建新数组即可删除重复项。
在 swift 中有很多方法可以从数组中删除重复项,但我正在尝试使用 for in loop 来管理它。 谁能解释一下,为什么这段代码不起作用?
Fatal error: Index out of range
func deleteDuplicates(array: [Int]) -> [Int] {
var newArray = array
for i in 0 ..< newArray.count - 1 {
for j in i + 1 ..< newArray.count {
if newArray[i] == newArray[j] {
newArray.remove(at: j)
}
}
}
return newArray
}
array1 = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
deleteDuplicates(array: array1)
一个原因是您正在修改同一个数组,您在该数组上 运行 两个 for 循环。要详细了解,请按照 Martin 所说的那样使用调试器。并且
这可以使用一个 for 循环和 Set 来完成:
var newArray = [0, 1, 8, 3, 4, 4, 3, 6, 7, 11, 4, 5, 5, 8]
var array = Set<Int>()
for i in newArray {
array.insert(i)
}
print(array)
输出:
[4, 5, 3, 0, 1, 8, 6, 11, 7]
有问题的部分是遍历数组并同时更新该数组。在这种情况下,在迭代时删除一个元素。
删除元素会减少数组长度 (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([=14=]).inserted }
这是您可以尝试的一种简单方法。
func removeDuplicates(_ nums: inout [Int]) {
var arrLen = nums.count
var index = 0
while(index < arrLen - 1){
if nums[index] == nums[index+1] {
nums.remove(at: index)
arrLen = arrLen - 1
}else{
index = index+1
}
}
}
无需创建新数组即可删除重复项。