递归函数无法终止:二维数组按指定列分组问题排查
问题分析与解决方案
为什么你的递归函数无法终止且重复执行?
你的递归逻辑有个关键漏洞:当找到拆分点并触发递归调用后,当前的for循环并没有停止执行。举个实际场景的例子:
- 假设在索引
x处发现第7列的值和x+1不同,你调用splitArray(fromArray: array, startIndex: x+1)处理后续元素; - 但递归返回后,原来的
for循环会继续执行x += 1,接着检查x+1的元素,这会导致同一个拆分点被多次处理,甚至重复触发递归,最终函数无法按预期终止,还会出现重复执行的情况。
另外,你的函数目前没有任何收集子数组的逻辑,只是在做递归遍历,自然无法生成你需要的拆分结果。
优化方案:用迭代实现更清晰可靠
递归在这里其实是不必要的,用迭代的方式可以更直观地控制流程,也更容易避免循环和递归的冲突。下面是实现思路和代码:
实现思路
- 跳过索引0的元素,从索引1开始处理;
- 维护一个
currentStart变量,记录当前子数组的起始索引; - 遍历数组(从1到末尾),每次检查当前元素和下一个元素的第7列值:
- 如果不同,就从
currentStart到当前索引x切分子数组,加入结果集合; - 更新
currentStart为x+1;
- 如果不同,就从
- 遍历结束后,别忘了把最后一段(从
currentStart到数组末尾)也加入结果。
Swift 代码实现
static func splitArray(fromArray array: [[String]]) -> [[[String]]] { // 空数组或只有索引0的元素,直接返回空结果 guard array.count > 1 else { return [] } // 提前检查所有元素的列数是否足够,避免越界错误 guard array.allSatisfy({ $0.count > 7 }) else { fatalError("数组中存在元素的列数不足8列,无法访问第7列") } var result = [[[String]]]() var currentStart = 1 for x in 1..<array.count { // 检查是否有下一个元素,且当前与下一个元素的第7列值不同 if x + 1 < array.count && array[x][7] != array[x+1][7] { // 切分当前子数组并加入结果 let subArray = Array(array[currentStart...x]) result.append(subArray) currentStart = x + 1 } } // 处理最后一段未被拆分的子数组 if currentStart < array.count { let lastSubArray = Array(array[currentStart...array.count-1]) result.append(lastSubArray) } return result }
如果一定要用递归实现
如果你坚持想用递归,需要修改逻辑:找到当前子数组的结束点后终止循环,并且通过返回值收集子数组,避免重复遍历。示例代码如下:
static func splitArrayRecursive(fromArray array: [[String]], startIndex: Int = 1) -> [[[String]]] { guard startIndex < array.count else { return [] } guard array.allSatisfy({ $0.count > 7 }) else { fatalError("数组中存在元素的列数不足8列,无法访问第7列") } var currentEnd = startIndex // 找到当前子数组的结束索引(直到下一个元素第7列值不同) while currentEnd + 1 < array.count && array[currentEnd][7] == array[currentEnd+1][7] { currentEnd += 1 } // 切分当前子数组 let subArray = Array(array[startIndex...currentEnd]) // 递归处理剩余部分并合并结果 let remainingSubArrays = splitArrayRecursive(fromArray: array, startIndex: currentEnd + 1) return [subArray] + remainingSubArrays }
这个递归版本的逻辑是:每次只处理当前未拆分的一段,找到结束点后就停止遍历,递归处理剩余元素,这样不会出现重复执行的问题。
内容的提问来源于stack exchange,提问作者Hapeki
相关产品推荐
相关产品推荐

