Swift中按指定大小拆分[String]数组为二维数组的最优方法
嘿,这个问题挺有意思的!在Swift里用函数式方法优雅地拆分数组,确实比手动写循环要清爽得多。先澄清一下:你给出的示例看起来是重叠式拆分(每个子数组的起始位置衔接前一个子数组的末尾元素,步长为指定大小-1),而通常我们说的“拆分”一般是非重叠的。我把两种场景的实现都给你写出来,方便你按需选择~
方法一:常规非重叠拆分(最后一个数组可小于指定大小)
这种是最常用的拆分方式,用stride结合map就能实现一行式的简洁代码:
extension Array { func splitIntoChunks(of size: Int) -> [[Element]] { // 生成所有子数组的起始索引,步长为指定大小 stride(from: 0, to: count, by: size).map { startIndex in // 计算当前子数组的结束索引,避免越界 let endIndex = Swift.min(startIndex + size, count) // 从原数组切片并转成新数组 return Array(self[startIndex..<endIndex]) } } } // 测试示例数组(常规拆分结果) let originalArray = ["1","2","3","4","5","6","7","8","9"] let nonOverlappingResult = originalArray.splitIntoChunks(of: 4) print(nonOverlappingResult) // 输出:[["1", "2", "3", "4"], ["5", "6", "7", "8"], ["9"]]
这个方法的优势是高效且易读,完全利用Swift的函数式特性,没有冗余的循环逻辑。
方法二:重叠式拆分(匹配你给出的示例结果)
如果你的需求确实是像示例那样的重叠拆分(每个子数组从前面子数组的最后一个元素开始),用reduce来实现会非常优雅:
extension Array { func overlappingSplit(into chunksOf size: Int) -> [[Element]] { guard size > 0 else { return [] } // 用reduce累加结果数组 return reduce(into: [[Element]]()) { result, element in if let lastChunk = result.last, lastChunk.count < size { // 如果最后一个子数组还没满,直接追加当前元素 result[result.count - 1].append(element) } else { // 生成新的子数组:如果不是第一个,取前一个子数组的最后(size-1)个元素 + 当前元素 let newChunk: [Element] if let lastChunk = result.last { newChunk = Array(lastChunk.suffix(size - 1)) + [element] } else { newChunk = [element] } result.append(newChunk) } } } } // 测试示例数组(重叠拆分结果) let originalArray = ["1","2","3","4","5","6","7","8","9"] let overlappingResult = originalArray.overlappingSplit(into: 4) print(overlappingResult) // 输出:[["1", "2", "3", "4"], ["4", "5", "6", "7"], ["7", "8", "9"]]
这个实现通过reduce逐步构建结果数组,每一步都判断当前元素应该追加到现有子数组还是生成新的重叠子数组,完全符合函数式编程的风格,不需要手动管理循环索引。
内容的提问来源于stack exchange,提问作者Chetan Pote
相关产品推荐
相关产品推荐

