I'm building an app in swift which displays several graphs, one of which is a graph of exchange rates which can be filtered by currency code and date range within a UITableView. I'm able to successfully pull the FX data from https://fixer.io/ and convert that json data into the following swift struct:
struct FetchedFXRateByDate: Codable {
let success, timeseries: Bool
let startDate, endDate, base: String
let rates: [String: [String: Double]] // [Date: [Currency Code : Amount]]
enum CodingKeys: String, CodingKey {
case success, timeseries
case startDate = "start_date"
case endDate = "end_date"
case base, rates
}
}
What I now want, is to manipulate or 'map'/'filter' the inner dict 'let rates: [String: [String: Double]]', to convert the dict:
From:
[String: [String: Double]] // [Date: [Currency Code : Amount]]
To:
[String: [String: Double]] // [Currency Code: [Date : Amount]]
Effectively swapping the keys. This can easily be done by a for loop with the keys, but I need a more efficient way to achieve the task. This is so i can draw the graph in the below interface:
Any help is greatly appreciated!
CodePudding user response:
A possible way is to use reduce(into:_:)
:
With sample:
let rates: [String: [String: Double]] = ["2021-11-14": ["CAD": 1.1,
"USD": 1.0,
"EUR": 0.9],
"2021-11-15": ["CAD": 1.11,
"USD": 1.01,
"EUR": 0.91]]
This should do the trick:
let target = rates.reduce(into: [String: [String: Double]]()) { partialResult, current in
let date = current.key
let dayRates = current.value
dayRates.forEach { aDayRate in
var currencyRates = partialResult[aDayRate.key, default: [:]]
currencyRates[date] = aDayRate.value
partialResult[aDayRate.key] = currencyRates
}
}
For the logic, we iterate over each elements of rates
.
For each [CurrencyCode: Amount], we iterate on them, and set them to partialResult
(which at the end of the inner loop of reduce(into:_:)
will be the finalResult
, ie the returned value).
Outputs for print(rates)
& print(target)
(I just formatted them to make them easier to read):
$> ["2021-11-14": ["CAD": 1.1, "EUR": 0.9, "USD": 1.0],
"2021-11-15": ["USD": 1.01, "EUR": 0.91, "CAD": 1.11]]
$> ["EUR": ["2021-11-14": 0.9, "2021-11-15": 0.91],
"USD": ["2021-11-15": 1.01, "2021-11-14": 1.0],
"CAD": ["2021-11-14": 1.1, "2021-11-15": 1.11]]