如何在Swift中按元素总值拆分数组为指定上限的块?
数组按总值上限拆分的Swift实现优化
需求说明
需要将包含FooBar元素的数组拆分为多个子数组,要求每个子数组中所有元素的value属性总和不超过指定上限(示例中为3)。
原数据结构与示例数组
struct FooBar { let value: Int } let array: [FooBar] = [ FooBar(value: 1), FooBar(value: 2), FooBar(value: 1), FooBar(value: 1), FooBar(value: 1), FooBar(value: 2), FooBar(value: 2), FooBar(value: 1) ]
预期拆分结果
let ExpectedEndResult: [[FooBar]] = [ [ FooBar(value: 1), FooBar(value: 2) ], [ FooBar(value: 1), FooBar(value: 1), FooBar(value: 1) ], [ FooBar(value: 2), ], [ FooBar(value: 2), FooBar(value: 1) ] ]
现有代码问题分析
当前实现的chunked(maxValue:)方法存在核心逻辑缺陷:
- 仅判断当前元素与下一个元素的
value之和是否超上限,未计算当前子数组的累计总和,导致无法识别多个元素总和符合要求的情况(比如三个value=1的元素总和为3,本应归为一个子数组,但现有代码无法实现)。 - 依赖数组索引判断逻辑,实现冗余且不直观。
优化后的实现方案
通过跟踪当前子数组的累计总和,遍历数组时动态判断元素归属,实现更准确简洁的逻辑:
extension Array where Element == FooBar { func chunked(maxTotalValue: Int) -> [[FooBar]] { var chunks: [[FooBar]] = [] var currentChunk: [FooBar] = [] var currentTotal = 0 for element in self { // 检查添加当前元素后是否超过总值上限 if currentTotal + element.value <= maxTotalValue { currentChunk.append(element) currentTotal += element.value } else { // 存入当前子数组,开启新的子数组 chunks.append(currentChunk) currentChunk = [element] currentTotal = element.value } } // 处理遍历结束后剩余的最后一个子数组 if !currentChunk.isEmpty { chunks.append(currentChunk) } return chunks } }
代码说明
- 用
currentTotal实时记录当前子数组的value总和,每次添加元素前做合规性判断。 - 当添加当前元素会超出上限时,先将当前子数组存入结果集,再以当前元素初始化新的子数组。
- 遍历结束后,确保最后一个非空的子数组被加入结果。
验证结果
调用array.chunked(maxTotalValue: 3)即可得到与预期完全一致的拆分结果。
内容的提问来源于stack exchange,提问作者Paul Peelen
相关产品推荐
相关产品推荐

