I have an array of Objects fetched from an API. An example would be:
static let previewPriceData: [PriceData] = [
PriceData(date: "2022-04-19", close: 41.45),
PriceData(date: "2022-04-20", close: 41.45),
PriceData(date: "2022-04-21", close: 41.45),
PriceData(date: "2022-04-22", close: 41.45),
PriceData(date: "2022-04-23", close: 41.45),
PriceData(date: "2022-04-24", close: 41.45),
PriceData(date: "2022-04-25", close: 41.45),
PriceData(date: "2022-04-26", close: 41.45),
PriceData(date: "2022-04-27", close: 41.45),
PriceData(date: "2022-04-28", close: 41.45),
PriceData(date: "2022-04-29", close: 41.45),
PriceData(date: "2022-04-30", close: 41.45),
PriceData(date: "2022-05-01", close: 45.45),
PriceData(date: "2022-05-02", close: 43.45),
PriceData(date: "2022-05-03", close: 42.45),
PriceData(date: "2022-05-04", close: 45.45),
PriceData(date: "2022-05-05", close: 43.45),
PriceData(date: "2022-05-06", close: 47.45),
PriceData(date: "2022-05-07", close: 46.45),
PriceData(date: "2022-05-08", close: 37.45),
PriceData(date: "2022-05-09", close: 35.45),
PriceData(date: "2022-05-10", close: 32.45),
PriceData(date: "2022-05-11", close: 29.45),
--> // Part of May missing
PriceData(date: "2022-06-01", close: 45.45),
PriceData(date: "2022-06-02", close: 43.45),
PriceData(date: "2022-06-03", close: 42.45),
PriceData(date: "2022-06-04", close: 45.45),
PriceData(date: "2022-06-05", close: 43.45),
PriceData(date: "2022-06-06", close: 47.45),
PriceData(date: "2022-06-07", close: 46.45),
PriceData(date: "2022-06-08", close: 37.45),
PriceData(date: "2022-06-09", close: 35.45),
PriceData(date: "2022-06-10", close: 32.45),
PriceData(date: "2022-06-11", close: 29.45),
PriceData(date: "2022-06-12", close: 35.45),
PriceData(date: "2022-06-13", close: 48.45),
PriceData(date: "2022-06-14", close: 52.45),
PriceData(date: "2022-06-15", close: 51.45),
PriceData(date: "2022-06-16", close: 49.45),
PriceData(date: "2022-06-17", close: 46.45),
PriceData(date: "2022-06-18", close: 45.45),
PriceData(date: "2022-06-19", close: 44.45),
PriceData(date: "2022-06-20", close: 43.45),
PriceData(date: "2022-06-21", close: 45.45),
PriceData(date: "2022-06-22", close: 46.45),
PriceData(date: "2022-06-23", close: 49.45),
PriceData(date: "2022-06-24", close: 51.45),
PriceData(date: "2022-06-25", close: 50.45),
PriceData(date: "2022-06-26", close: 48.45),
PriceData(date: "2022-06-27", close: 43.45),
PriceData(date: "2022-06-28", close: 39.45),
PriceData(date: "2022-06-29", close: 34.45),
PriceData(date: "2022-06-30", close: 32.45),
PriceData(date: "2022-07-01", close: 45.45),
PriceData(date: "2022-07-02", close: 43.45),
PriceData(date: "2022-07-03", close: 42.45),
PriceData(date: "2022-07-04", close: 45.45),
PriceData(date: "2022-07-05", close: 43.45)
]
This array contains price data on a daily basis for an interval of 5 years, But it returns not every time every day. There can be gaps like here in May 2022. I use the data to display It inside a chart. To not fill the chart with extraordinary much data I want to change the daily data from this 5 years interval to a monthly. This is not possible with the API, unfortunately.
My approach was this:
func extractData(_ dataArray: [PriceData]) -> [PriceData] {
/// Date / Date-Formatter
let calendar = Calendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
/// First price Value
guard let firstValue = dataArray.first, let firstDate = firstValue.date else {
return []
}
/// Set starter Month based on Firest price Value
guard var starterMonthDate = dateFormatter.date(from: firstDate) else {
return []
}
// Extracted Data with firstValue
var extractedData: [PriceData] = [firstValue]
var preFilterArray: [PriceData] = []
var preArray: [PriceData] = []
var emptyMonthAndYear: [DateComponents] = []
for data in dataArray.dropFirst() {
/// Convert String-Date to Date
guard let dateString = data.date, let date = dateFormatter.date(from: dateString) else { continue }
/// Fill array with fitting data
var starterMonthComponents = calendar.dateComponents([.year, .month], from: starterMonthDate)
let dataDateComponents = calendar.dateComponents([.year, .month], from: date)
if dataDateComponents != starterMonthComponents {
starterMonthComponents = dataDateComponents
}
if let dateApproved = getDateWithMonthAndYear(date),
date == dateApproved,
dataDateComponents == starterMonthComponents {
extractedData.append(data)
starterMonthDate = incrementMonth(of: starterMonthDate) ?? starterMonthDate
removeAllOccurrences(of: dataDateComponents, from: &emptyMonthAndYear)
continue
} else if let dateApproved = getDateWithMonthAndYear(date), date != dateApproved, dataDateComponents == starterMonthComponents {
if !emptyMonthAndYear.contains(dataDateComponents) {
emptyMonthAndYear.append(dataDateComponents)
}
}
}
for emptyDateComponents in emptyMonthAndYear {
for data in dataArray.dropFirst() {
guard let dateString = data.date, let date = dateFormatter.date(from: dateString) else { continue }
let dataDateComponents = calendar.dateComponents([.year, .month], from: date)
if dataDateComponents == emptyDateComponents {
preArray.append(data)
}
}
if !preArray.isEmpty {
let median = preArray.sorted(by: { $0.close < $1.close })[preArray.count / 2]
extractedData.append(median)
}
}
if let lastValue = dataArray.last {
extractedData.append(lastValue)
}
// print(extractedData)
return extractedData
}
with this function I append the first and last value of the array. Then I try to append for each month between this first and last value one value. here I wanted to take yesterday and add that day's value for each month:
if first value = PriceData(date: "2022-04-19", close: 41.45)
if last value = PriceData(date: "2022-07-21", close: 43.45)
I take the 2022-07-20 and append it, then go one month backwards and append the next one (2022-06-20) and so on.
My Problem was how to handle if on this specific day is no data available like here on the month May where is no data for 2022-05-20.
I would be grateful for any help