这是字典:
[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))
}
}
})
这是我上一个问题的答案中提供的代码:Calculating doubles by dates with format timeIntervalSince1970 from 2 different dictionaries
但是此代码返回了我重复的值
打印(cryptosPerDay)
["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)]]
如何修复?
答案 0 :(得分:1)
另一个问题的答案远非理想。这是一种将[Int64: [String: String]]
转换为按天分组的更简单方法(使用Date
,而不是String
)。
let cryptoData: [Int64: [String: String]] = [
1549424985: ["amount": "10.0", "symbol": "XRP"],
1546531017: ["amount": "1.0", "symbol": "ETH"],
1549424153: ["amount": "50.0", "symbol": "EOS"],
1546531031: ["amount": "200.0", "symbol": "XRP"],
]
let cryptosPerDay = cryptoData.reduce(into: [Date: [[String: String]]]()) { (result, element) in
result[Calendar.current.startOfDay(for: Date(timeIntervalSince1970: TimeInterval(element.key))), default: []].append(element.value)
}
print(cryptosPerDay)
输出:
[2019-01-03 07:00:00 +0000:[[“金额”:“ 1.0”,“符号”:“ ETH”],[“符号”:“ XRP”,“金额”:“ 200.0“]],2019-02-05 07:00:00 +0000:[[”符号“:” EOS“,”金额“:” 50.0“],[”金额“:” 10.0“,”符号“: “ XRP”]]]
请记住,Date
键代表当地时间的午夜。根据您的时区,您的结果会略有不同。
或者与您的CryptoTuple
:
let cryptosPerDay = cryptoData.reduce(into: [Date: [CryptoTuple]]()) { (result, keyvalue) in
result[Calendar.current.startOfDay(for: Date(timeIntervalSince1970: TimeInterval(keyvalue.key))), default: []].append((symbol: keyvalue.value["symbol"]!, amount: Double(keyvalue.value["amount"]!)!))
}
答案 1 :(得分:1)
目前尚不清楚目标是什么,但是这是一种我想做的方法。注意使用结构而不是元组:
let d = [ // your data
1549424985: ["amount": "10.0", "symbol": "XRP"],
1546531017: ["amount": "1.0", "symbol": "ETH"],
1549424153: ["amount": "50.0", "symbol": "EOS"],
1546531031: ["amount": "200.0", "symbol": "XRP"]
]
struct Trade {
let amount:Double
let symbol:String
}
var result = [String:[Trade]]()
for key in d.keys {
let date = Date(timeIntervalSince1970: Double(key))
let f = DateFormatter()
f.dateFormat = "yyyy-MM-dd"
let dayString = f.string(from: date)
let val = d[key] as! [String:String]
let trade = Trade(
amount: Double(val["amount"]!)!,
symbol: val["symbol"]!
)
result[dayString, default:[]].append(trade)
}
之后,result
是:
["2019-02-06": [Trade(amount: 10.0, symbol: "XRP"), Trade(amount: 50.0, symbol: "EOS")],
"2019-01-04": [Trade(amount: 1.0, symbol: "ETH"), Trade(amount: 200.0, symbol: "XRP")]]
...这似乎是“正确”的答案。就我个人而言,我认为以这种方式使用日期字符串是很愚蠢的。最好使用实际日期。在这种情况下,最后一部分可以重写为:
var result = [Date:[Trade]]()
for key in d.keys {
let date = Date(timeIntervalSince1970: Double(key))
let day = Calendar(identifier: .gregorian).startOfDay(for: date)
let val = d[key] as! [String:String]
let trade = Trade(
amount: Double(val["amount"]!)!,
symbol: val["symbol"]!
)
result[day, default:[]].append(trade)
}
答案 2 :(得分:0)
您可以使用Dictionary(grouping:by:)对包括字典的任何序列的元素进行分组。
let result:[String:[[String:String]]] = Dictionary(grouping: cryptoData) { parseToDateString($0.key) }.mapValues { $0.compactMap({ $0.value }) }
print(result)
[“ 2019-01-03”:[[“金额”:“ 200.0”,“符号”:“ XRP”],[“金额”: “ 1.0”,“ symbol”:“ ETH”]],
“ 2019-02-06”:[[“金额”:“ 10.0”,“符号”:“ XRP”],[“金额”:“ 50.0”,“符号”:“ EOS”]]]] < / p>
使用元组
let result:[String:[CryptoTuple]] = Dictionary(grouping: cryptoData) { parseToDateString($0.key) }.mapValues { $0.compactMap({
if let symbol = $0.value["symbol"], let amountStr = $0.value["amount"], let amount = Double(amountStr) {
return (symbol, amount)
} else { return nil }
}) }
使用结构
struct Crypto {
var symbol: String
var amount: Double
init?(_ dict:[String: String]) {
if let symbol = dict["symbol"], let amountStr = dict["amount"], let amount = Double(amountStr) {
self.symbol = symbol
self.amount = amount
} else {
return nil
}
}
}
let result:[String:[Crypto]] = Dictionary(grouping: cryptoData) { parseToDateString($0.key) }.mapValues { $0.compactMap({ Crypto($0.value) }) }
答案 3 :(得分:0)
您需要首先检查数组中是否存在给定符号的元组,如果是,则将其与新符号合并,而不是附加新元组。
将循环末尾的else
子句更改为
if let index = cryptosPerDay[date]?.firstIndex(where: {$0.symbol == symbol}) {
let total = (cryptosPerDay[date]?[index].amount ?? 0) + amount
cryptosPerDay[date]?[index] = (symbol, total)
} else {
cryptosPerDay[date]?.append((symbol, amount))
}