如何实现嵌套循环的单次调用式分步比较?
动态数组组合的按需迭代比较实现
需求背景
处理任意数量的等长数组,原本通过嵌套循环遍历所有元素组合完成比较,现需改为按需触发单次比较,支持两种调用模式:
- 通过指定迭代序号直接定位到某一组元素组合执行比较
- 通过
next()方法按顺序逐个触发下一组元素的比较
方案1:支持指定迭代序号的compare(iteration:)
核心逻辑是将一维的迭代序号转换为多维数组的索引(本质是进制转换),把十进制序号转为n进制数(n为单个数组的长度),每一位对应一个数组的索引。
class Comparator { private let arrays: [[Int]] private let arrayCount: Int private let elementCount: Int init(arrays: [[Int]]) { self.arrays = arrays self.arrayCount = arrays.count self.elementCount = arrays.first?.count ?? 0 // 强制校验所有数组长度一致 precondition(arrays.allSatisfy { $0.count == elementCount }, "所有输入数组长度必须相等") } func compare(iteration: Int) -> Bool? { let totalCombinations = Int(pow(Double(elementCount), Double(arrayCount))) guard iteration >= 0, iteration < totalCombinations else { print("迭代序号超出有效范围") return nil } // 将迭代序号转为各数组对应的索引 var indices = [Int]() var remaining = iteration for _ in 0..<arrayCount { indices.append(remaining % elementCount) remaining /= elementCount } // 反转索引顺序,匹配原嵌套循环的从外到内逻辑 indices.reverse() // 获取当前组合的所有元素 let elements = zip(arrays, indices).map { $0[$1] } // 这里替换为你的实际比较逻辑,示例为判断所有元素相等 let comparisonResult = elements.allSatisfy { $0 == elements.first } print("当前比较元素:\(elements),结果:\(comparisonResult)") return comparisonResult } } // 使用示例 let a = [1, 2, 3] let b = [3, 4, 5] let c = [4, 5, 6] let comparator = Comparator(arrays: [a, b, c]) comparator.compare(iteration: 0) // 比较 [1, 3, 4] comparator.compare(iteration: 1) // 比较 [1, 3, 5] comparator.compare(iteration: 9) // 比较 [2, 3, 4]
方案2:支持next()的迭代器模式
维护当前的索引状态数组,每次调用next()时按嵌套循环的顺序推进索引,直到遍历完所有元素组合。
class ComparatorIterator: IteratorProtocol { typealias Element = [Int] private let arrays: [[Int]] private let arrayCount: Int private let elementCount: Int private var currentIndices: [Int] private var hasNext: Bool init(arrays: [[Int]]) { self.arrays = arrays self.arrayCount = arrays.count self.elementCount = arrays.first?.count ?? 0 precondition(arrays.allSatisfy { $0.count == elementCount }, "所有输入数组长度必须相等") // 初始索引全为0 self.currentIndices = Array(repeating: 0, count: arrayCount) self.hasNext = arrayCount > 0 && elementCount > 0 } func next() -> [Int]? { guard hasNext else { return nil } // 获取当前元素组合 let elements = zip(arrays, currentIndices).map { $0[$1] } // 更新索引,模拟嵌套循环的递进逻辑 var index = arrayCount - 1 while index >= 0 { currentIndices[index] += 1 if currentIndices[index] < elementCount { break } currentIndices[index] = 0 index -= 1 // 所有索引重置为0时,标记遍历完成 if index < 0 { hasNext = false } } // 执行自定义比较逻辑,示例为打印结果 let comparisonResult = elements.allSatisfy { $0 == elements.first } print("当前比较元素:\(elements),结果:\(comparisonResult)") return elements } } // 使用示例 let iterator = ComparatorIterator(arrays: [a, b, c]) iterator.next() // 输出 [1, 3, 4] iterator.next() // 输出 [1, 3, 5] iterator.next() // 输出 [1, 3, 6] iterator.next() // 输出 [1, 4, 4] // ... 持续调用直到遍历完所有27组组合
关键注意事项
- 数组长度校验:初始化时加入断言,避免因数组长度不一致导致逻辑错误
- 比较逻辑自定义:示例中的比较逻辑为判断所有元素相等,实际使用时可替换为任意业务规则(如元素求和、自定义阈值判断等)
- 性能优化:两种方案单次调用的时间复杂度均为O(k)(k为数组数量),适配大多数场景;若数组数量极大,可优化进制转换的计算逻辑
内容的提问来源于stack exchange,提问作者Kevvv
相关产品推荐
相关产品推荐

