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

Swift按年度周数分组数组并聚合对应商品销量

问题描述

处理包含日期、Double值和字符串的年度对象数组,需要按年度周数和商品名称分组并累加销量。当前代码仅能累加每周总销量,且存在重复输出问题,多次尝试mapValues仍无法得到目标格式。

当前输出:

["Location1": ["Location1": [1: 12.0], "Location#2": [3: 16.0]], "Location2": ["Location1": [1: 12.0], "Location#2": [3: 16.0]]]

期望输出格式:

["Location1": [1: ["Apple": 5, "Pear": 7]], "Location2": [3: ["Apple": 7, "Pear": 9]]]
// 结构说明:["Location": [weekOfYear: ["itemName": qtySold]]]

修正后的代码
import Foundation

let cal = Calendar.current

extension Date {
    var week: Int {
        return cal.component(.weekOfYear, from: self)
    }
    var weekAndYear: DateComponents {
        return cal.dateComponents([.weekOfYear, .yearForWeekOfYear], from: self)
    }
    
    var yearForWeekOfYear: Int {
        return cal.component(.yearForWeekOfYear, from: self)
    }
}

struct SaleRecord { // 重命名结构体,贴合数据语义
    var date: Date
    var itemName: String
    var itemSold: Double
}

// 日期转换逻辑简化
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let date1 = dateFormatter.date(from: "2023-01-04") ?? Date()
let date2 = dateFormatter.date(from: "2023-01-05") ?? Date()
let date3 = dateFormatter.date(from: "2023-01-06") ?? Date()
let date4 = dateFormatter.date(from: "2023-01-17") ?? Date()
let date5 = dateFormatter.date(from: "2023-01-18") ?? Date()

// 修正数据源的位置名称,匹配目标输出
let allInfo: [String: [SaleRecord]] = [
    "Location1": [
        SaleRecord(date: date1, itemName: "Apple", itemSold: 3.0),
        SaleRecord(date: date2, itemName: "Pear", itemSold: 7),
        SaleRecord(date: date3, itemName: "Apple", itemSold: 2)
    ],
    "Location2": [
        SaleRecord(date: date4, itemName: "Apple", itemSold: 7),
        SaleRecord(date: date5, itemName: "Pear", itemSold: 9)
    ]
]

// 明确结果字典类型,避免Any带来的类型歧义
var result: [String: [Int: [String: Double]]] = [:]

// 遍历每个位置处理对应销售数据
for (location, sales) in allInfo {
    // 第一步:按周分组当前位置的销售记录
    let groupedByWeek = Dictionary(grouping: sales, by: { $0.date.week })
    
    // 第二步:对每周数据,按商品名称分组并累加销量
    let weeklyItemSales = groupedByWeek.mapValues { weeklySales in
        Dictionary(grouping: weeklySales, by: { $0.itemName })
            .mapValues { itemSales in
                itemSales.map { $0.itemSold }.reduce(0, +)
            }
    }
    
    result[location] = weeklyItemSales
}

print(result)

关键修改说明
  1. 语义化优化:将sortedDates重命名为SaleRecord,简化冗余的日期字符串拼接逻辑,提升代码可读性。
  2. 数据源修正:原数据中Location#2与目标输出的Location2不匹配,修正后确保数据对应关系正确。
  3. 嵌套分组逻辑:
    • 先按周对当前位置的销售记录做第一层分组
    • 对每周的记录,再按商品名称做第二层分组,最后累加每个商品的销量
  4. 类型明确化:将结果字典类型从[String: Any]改为[String: [Int: [String: Double]]],完全匹配期望的输出结构,避免类型模糊问题。
  5. 遍历逻辑修正:直接遍历allInfo的键值对,确保每个位置只处理自身的销售数据,彻底解决重复输出问题。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.04 07:25:35