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

