You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

SwiftUI 购物车Drink结构体重复项按数量合并删除实现问题

错误原因排查
  • 索引越界:你遍历的是数组初始状态的索引集合,执行remove(at:)后数组实际长度缩小,但循环仍使用原始索引访问元素,尤其是你直接访问i+1,当i为数组最后一个索引时必然超出有效范围。
  • 相邻判断逻辑不成立:你仅对索引按名称排序,没有实际重排cartDrinks数组的元素顺序,相同名称的饮品并不会相邻,判断cartDrinks[i].name == cartDrinks[i+1].name的逻辑本身无法生效。
  • 遍历修改冲突:即使先对数组排序,正序遍历过程中删除元素会导致后续元素的索引全部前移,会出现漏检元素的问题。
正确实现方案

推荐使用字典分组的方案,无索引操作风险,逻辑更稳定:

func mergeItem() {
    // 按饮品名称对购物车元素分组
    let groupedDrinks = Dictionary(grouping: cartDrinks, by: \.name)
    // 重构合并后的购物车数组
    cartDrinks = groupedDrinks.compactMap { group in
        // 取同组第一个元素作为基准(默认相同名称的饮品其他属性一致)
        guard var baseDrink = group.value.first else { return nil }
        // 需求为每个重复条目给基准unit加1,使用如下逻辑
        baseDrink.unit += group.value.count - 1
        // 如果需要累加所有条目的unit数量,替换为以下代码
        // baseDrink.unit = group.value.reduce(0) { $0 + $1.unit }
        return baseDrink
    }
    // 如果需要保留原数组的排序规则,可在此处添加排序逻辑,例如按添加日期排序:
    // cartDrinks.sort { $0.date < $1.date }
}

如果你偏好遍历修改数组的实现方式,可以使用倒序遍历方案,避免索引错位:

func mergeItem() {
    // 先按名称排序数组,让相同名称的元素相邻
    cartDrinks.sort { $0.name < $1.name }
    // 倒序遍历,删除元素不会影响未遍历的前序索引
    var i = cartDrinks.count - 1
    while i > 0 {
        if cartDrinks[i].name == cartDrinks[i-1].name {
            cartDrinks[i-1].unit += 1
            // 如需累加unit,替换为:cartDrinks[i-1].unit += cartDrinks[i].unit
            cartDrinks.remove(at: i)
        }
        i -= 1
    }
}

内容的提问来源于stack exchange,提问作者Liangn1an

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.27 07:45:04