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

Swift按日期分组字典数据出现重复值,如何修复?

解决加密货币按日期分组时的重复值问题

问题回顾

你有一组以时间戳为键的加密货币交易数据:

[1549424985: ["amount": "10.0", "symbol": "XRP"], 
1546531017: ["amount": "1.0", "symbol": "ETH"], 
1549424153: ["amount": "50.0", "symbol": "EOS"], 
1546531031: ["amount": "200.0", "symbol": "XRP"]]

尝试用以下代码按日期分组后,结果出现了重复的币种条目:

typealias CryptoTuple = (symbol: String, amount: Double)
var cryptosPerDay = [String: [CryptoTuple]]()
var prev = ""
groupedData.keys.sorted(by: <).forEach( { key in
    let date = parseToDateString(key)
    if let buy = groupedData[key], let symbol = buy["symbol"], let amountStr = buy["amount"], let amount = Double(amountStr) {
        if prev != date {
            cryptosPerDay[date] = [(symbol, amount)]
            if let old = cryptosPerDay[prev] {
                cryptosPerDay[date]?.append(contentsOf: old)
            }
            prev = date
        } else {
            cryptosPerDay[date]?.append((symbol, amount))
        }
    }
})

输出结果:

["2019-02-06": [(symbol: "EOS", amount: 50.0), (symbol: "ETH", amount: 1.0), (symbol: "XRP", amount: 200.0), (symbol: "XRP", amount: 10.0)], "2019-01-03": [(symbol: "ETH", amount: 1.0), (symbol: "XRP", amount: 200.0)]]

问题原因

你的核心逻辑错在日期切换时的处理:每当进入新的日期,你直接把前一天的所有交易条目追加到了当天的列表里,而不是合并同币种的金额。比如2019-02-06的条目里,ETH和XRP的旧记录(来自2019-01-03)被直接加了进去,和当天的新交易混在一起,导致同一币种出现多条记录。

修复方案

根据你的需求,分两种场景给出解决方案:

场景1:累计历史金额(每个日期显示截至当天的各币种总金额)

我们可以维护一个字典追踪当前各币种的累计余额,处理每笔交易后更新余额,再将当前的余额状态存入对应日期:

typealias CryptoTuple = (symbol: String, amount: Double)
var cryptosPerDay = [String: [CryptoTuple]]()
// 追踪当前各币种的累计金额
var currentBalances = [String: Double]()

// 先按时间戳升序排序所有交易,保证处理顺序正确
let sortedKeys = groupedData.keys.sorted(by: <)

for key in sortedKeys {
    let date = parseToDateString(key)
    guard let buy = groupedData[key],
          let symbol = buy["symbol"],
          let amountStr = buy["amount"],
          let amount = Double(amountStr) else {
        continue
    }
    
    // 更新当前币种的累计金额
    currentBalances[symbol] = (currentBalances[symbol] ?? 0) + amount
    
    // 将当前所有币种的累计金额转为Tuple列表,存入对应日期
    let dailyBalances = currentBalances.map { (symbol: $0.key, amount: $0.value) }
    cryptosPerDay[date] = dailyBalances
}

运行后输出:

["2019-01-03": [(symbol: "ETH", amount: 1.0), (symbol: "XRP", amount: 200.0)], 
"2019-02-06": [(symbol: "EOS", amount: 50.0), (symbol: "ETH", amount: 1.0), (symbol: "XRP", amount: 210.0)]]

每个日期下的币种唯一,金额是截至当天的累计总和,完全消除重复。

场景2:仅保留当日交易(合并当天同币种的金额,不累计历史)

如果你的需求是每个日期只展示当天的交易,且当天同币种合并金额,可以先按日期分组原始交易,再对每个日期内的交易按币种求和:

typealias CryptoTuple = (symbol: String, amount: Double)
var cryptosPerDay = [String: [CryptoTuple]]()

// 第一步:按日期分组所有当日交易
var dailyTransactions = [String: [(symbol: String, amount: Double)]]()
for key in groupedData.keys {
    let date = parseToDateString(key)
    guard let buy = groupedData[key],
          let symbol = buy["symbol"],
          let amountStr = buy["amount"],
          let amount = Double(amountStr) else {
        continue
    }
    // 用default参数自动初始化空数组
    dailyTransactions[date, default: []].append((symbol, amount))
}

// 第二步:对每个日期内的交易按币种求和
for (date, transactions) in dailyTransactions {
    var dailySum = [String: Double]()
    for (symbol, amount) in transactions {
        dailySum[symbol] = (dailySum[symbol] ?? 0) + amount
    }
    cryptosPerDay[date] = dailySum.map { (symbol: $0.key, amount: $0.value) }
}

运行后输出:

["2019-01-03": [(symbol: "ETH", amount: 1.0), (symbol: "XRP", amount: 200.0)], 
"2019-02-06": [(symbol: "EOS", amount: 50.0), (symbol: "XRP", amount: 10.0)]]

总结

两种方案分别对应不同的业务需求,你可以根据实际需要选择。核心思路都是按币种进行金额合并,而不是简单叠加历史条目,这样就能避免重复值的出现。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.13 07:53:47