Scala中使用until的for循环出现意外行为求助
嘿,我一眼就看出你这段Scala代码里的问题啦——正向遍历数组并删除元素时,会跳过后续的匹配项,咱们来慢慢理清楚:
核心问题分析
你在removeAllbyName里用了for(i <- 0 until _highestIndex)的正向循环,当你调用deleteByIndex(i)删除元素时,数组中i位置之后的所有元素都会向前移动一位,同时_highestIndex应该会减1(我猜你代码里的deleteByIndex逻辑是这样的)。这就导致了一个问题:比如你删除了第i个元素,原本第i+1个元素现在移到了第i位,但循环下一次会直接跳到i+1,完全跳过了这个刚移过来的元素,自然会漏删符合条件的项。
举个简单例子:假设数组里有[张三, 李四, 张三],_highestIndex=3。当i=0删除第一个"张三"后,数组变成[李四, 张三],_highestIndex=2。循环接下来到i=1,此时i已经等于新的_highestIndex,循环直接结束,第二个"张三"就被漏掉了。
修复方案
最直接的解决办法是反向遍历数组——从最后一个元素往前检查,这样删除元素不会影响还没遍历到的前面的元素。同时我也帮你补全并修正了deleteByIndex的逻辑(你之前的代码没写完):
修正后的完整代码片段
private var _list = new Array[NAW](20) private var _highestIndex = 0 def removeAllbyName(name: String): Unit = { // 反向遍历:从最后一个有效元素的索引开始,倒着遍历到0 for (i <- (_highestIndex - 1) to 0 by -1) { if (_list(i).name == name) { deleteByIndex(i) } } } def deleteByIndex(i: Int): Unit = { // 先做边界检查,避免越界访问 if (i >= 0 && i < _highestIndex) { // 将i之后的元素依次向前移动一位 for (x <- i until _highestIndex - 1) { _list(x) = _list(x + 1) } // 有效元素数量减1 _highestIndex -= 1 // 可选:把原最后一个有效位置置为null,避免引用残留(如果NAW是引用类型) _list(_highestIndex) = null.asInstanceOf[NAW] } }
为什么反向遍历有效?
当你从后往前遍历的时候,删除某个位置的元素只会改变该位置之后的元素(但这些元素已经被检查过了),前面还没遍历到的元素位置完全不受影响,所以每个符合条件的元素都会被准确检查并删除,不会出现漏删的情况。
额外小提示
如果你的场景允许,也可以考虑用Scala的集合API来简化逻辑(比如过滤后重新填充数组),但考虑到你需要的是无空洞原地修改,反向遍历的方案是最贴合需求的。
内容的提问来源于stack exchange,提问作者Toricima

