Swift 4中过滤对象数组并移除元素:解决索引越界问题
解决数组遍历删除时的索引越界问题
嘿,我完全懂你遇到的这个坑!之前我也踩过类似的——用stride(from:to:by:)的时候,to参数会在循环开始前就固定为数组初始的count值,哪怕你中途删除元素改变了数组长度,循环还是会按原来的次数执行,自然就会碰到索引越界的问题。
下面给你两种最靠谱的解决方式,按需选择:
方法一:用filter过滤数组(推荐)
这是最简洁安全的方式,完全不需要手动处理索引。filter会创建一个新数组,只保留符合你条件的元素,直接避开了遍历删除的所有坑。
举个例子,假设你要移除数组中所有等于2的元素:
var numbers = [1, 2, 3, 2] // 过滤掉所有值为2的元素 numbers = numbers.filter { $0 != 2 } print(numbers) // 输出: [1, 3]
这种方式代码干净,性能也不错,除非你有必须原地修改数组的特殊需求,否则优先用这个。
方法二:原地删除的正确遍历方式
如果必须原地修改数组(比如删除时需要执行额外逻辑),推荐两种方式:
1. 倒序遍历
倒着遍历数组,删除元素不会影响前面未遍历的索引,因为前面的元素位置不会被移动。
var numbers = [1, 2, 3, 2] // 从最后一个索引开始,往前遍历 for i in stride(from: numbers.count - 1, through: 0, by: -1) { if numbers[i] == 2 { numbers.remove(at: i) print("Removed at index \(i), current count: \(numbers.count)") } } print(numbers) // 输出: [1, 3]
2. 使用while循环手动控制索引
用while循环动态检查数组的最新count,并且根据是否删除元素来决定是否递增索引:
var numbers = [1, 2, 3, 2] var i = 0 while i < numbers.count { if numbers[i] == 2 { numbers.remove(at: i) // 删除元素后,后面的元素会移到当前i的位置,所以不要递增索引 } else { // 没删除元素,正常递增索引 i += 1 } } print(numbers) // 输出: [1, 3]
这样就能避免你遇到的问题——每次循环都会用数组当前的count来判断,不会出现索引超出范围的情况。
内容的提问来源于stack exchange,提问作者Zack117
相关产品推荐
相关产品推荐

