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

如何优化电表读数图表数据的准备流程?

优化电表读数图表数据生成方案

针对你的需求,我们可以利用Swift标准库的高阶集合函数替代ForEach,直接基于ReadingET实体处理数据,跳过Consumption结构体的中转,以下是具体实现:

先修正重复定义的SeriesData

原代码中SeriesData存在重复的chartValues属性,这里调整为存储聚合后的读数数据:

struct SeriesData: Identifiable {
    var id: Int
    var chartLabel: String = ""
    // 存储聚合后的季度/月度/年度数据
    var chartValues: [AggregatedReading]
}

// 替代原Consumption的轻量聚合结构体,直接基于ReadingET的计算结果
struct AggregatedReading: Identifiable {
    let id = UUID()
    var year: String
    var quarter: String? // 仅季度数据填充
    var month: String?   // 仅月度数据填充
    var totalConsumption: Double
    var endDate: Date    // 对应周期的结束日期
}

季度数据生成(满足所有要求)

使用filter筛选目标年份数据,Dictionary(grouping:by:)按季度分组,reduce求和,全程无手动ForEach遍历:

private func getQuarterlyConsumptionByYear(year: Int) -> [AggregatedReading] {
    let targetYear = String(year)
    // 1. 筛选目标年份的读数
    let yearlyReadings = readings.filter { $0.readingYear == targetYear }
    
    // 2. 按季度分组
    let groupedByQuarter = Dictionary(grouping: yearlyReadings, by: { $0.readingQuarter })
    
    // 3. 定义季度与对应结束日期的配置(修正原代码中6月31日的错误)
    let quarterConfigs = [
        ("Q1", "03", "31"),
        ("Q2", "06", "30"),
        ("Q3", "09", "30"),
        ("Q4", "12", "31")
    ]
    
    // 4. 生成聚合数据
    return quarterConfigs.map { quarter, month, day in
        let quarterData = groupedByQuarter[quarter] ?? []
        // 用reduce计算该季度总用电量
        let totalConsumption = quarterData.reduce(0.0) { $0 + $1.readingConsumption }
        // 解析周期结束日期(假设你有Date的字符串解析扩展)
        let endDate = Date(fromString: "\(year)-\(month)-\(day)", format: .isoDate)!
        
        return AggregatedReading(
            year: targetYear,
            quarter: quarter,
            month: nil,
            totalConsumption: totalConsumption,
            endDate: endDate
        )
    }
}

月度/年度数据的类似实现

月度数据

private func getMonthlyConsumptionByYear(year: Int) -> [AggregatedReading] {
    let targetYear = String(year)
    let yearlyReadings = readings.filter { $0.readingYear == targetYear }
    let groupedByMonth = Dictionary(grouping: yearlyReadings, by: { $0.readingMonth })
    
    // 生成1-12月的配置,动态获取每月最后一天避免硬编码错误
    let monthConfigs = (1...12).map { month -> (String, String) in
        let monthStr = String(format: "%02d", month)
        let endDay = Calendar.current.range(of: .day, in: .month, for: DateComponents(year: year, month: month))?.count ?? 28
        return (monthStr, String(endDay))
    }
    
    return monthConfigs.map { monthStr, dayStr in
        let monthData = groupedByMonth[monthStr] ?? []
        let totalConsumption = monthData.reduce(0.0) { $0 + $1.readingConsumption }
        let endDate = Date(fromString: "\(year)-\(monthStr)-\(dayStr)", format: .isoDate)!
        
        return AggregatedReading(
            year: targetYear,
            quarter: nil,
            month: monthStr,
            totalConsumption: totalConsumption,
            endDate: endDate
        )
    }
}

年度数据

private func getYearlyConsumption() -> [AggregatedReading] {
    // 按年份分组并排序
    let groupedByYear = Dictionary(grouping: readings, by: { $0.readingYear })
        .sorted { $0.key < $1.key }
    
    return groupedByYear.map { year, yearData in
        let totalConsumption = yearData.reduce(0.0) { $0 + $1.readingConsumption }
        let endDate = Date(fromString: "\(year)-12-31", format: .isoDate)!
        
        return AggregatedReading(
            year: year,
            quarter: nil,
            month: nil,
            totalConsumption: totalConsumption,
            endDate: endDate
        )
    }
}

方案满足的要求说明

  • 避免ForEach:全程使用filter、Dictionary(grouping:by:)、map、reduce等高阶函数,无手动遍历逻辑
  • 利用便捷数组函数:依赖Swift标准库的集合操作API,代码更简洁易维护
  • 直接使用ReadingET:所有计算均基于原始ReadingET数组,无需通过Consumption结构体中转,仅用轻量的AggregatedReading存储聚合结果

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.24 10:29:57