I have an array of Swift dates:
[date1, date2, date3, ..., dateN]
I want to group these dates by month:
[
[date1, date2],
[date3],
...
[dateN],
]
All days of a month should be inside the same month array.
How can I group an array of dates by month, either functionally or imperatively?
Swift 4
This is how I would have done it:
extension Date {
var month: Int {
return Calendar.current.component(.month, from: self)
}
}
// some random arbitrary dates
let rawDates = [Date(), Date().addingTimeInterval(100000.0), Date().addingTimeInterval(100000000.0)]
// the desired format
var sortedDatesByMonth: [[Date]] = []
// a filter to filter months by a given integer, you could also pull rawDates out of the equation here, to make it pure functional
let filterDatesByMonth = { month in rawDates.filter { $0.month == month } }
// loop through the months in a calendar and for every month filter the dates and append them to the array
(1...12).forEach { sortedDatesByMonth.append(filterDatesByMonth($0)) }
Tested and working in a Xcode 9.2 playground.
Output
[[], [], [2018-03-21 12:29:10 +0000, 2018-03-22 16:15:50 +0000], [], [2021-05-21 22:15:50 +0000], [], [], [], [], [], [], []]
Usage for hypothetical AppointmentObject
extension Date {
var month: Int {
return Calendar.current.component(.month, from: self)
}
}
// some random arbitrary dates
let appointments = [AppointmentObject(), AppointmentObject(), AppointmentObject()]
// the desired format
var sortedAppointmentsByFromMonth: [[AppointmentObject]] = []
// a filter to filter months by a given integer, you could also pull rawDates out of the equation here, to make it pure functional
let filterFromDatesByMonth = { month in appointments.filter { $0.from.month == month } }
// loop through the months in a calendar and for every month filter the dates and append them to the array
(1...12).forEach { sortedAppointmentsByFromMonth.append(filterFromDatesByMonth($0)) }
Alternative
Not a direct answer to your question, but maybe a viable solution to your problem too. Many people, righteously, pointed out the existence of the Dictionary
class. Using the above mentioned Date
extension, you could also do this:
Dictionary(grouping: rawDates) {$0.month}
Output
Your keys are now the month indicators (5 being may and 3 march)
[5: [2021-05-21 22:46:44 +0000], 3: [2018-03-21 13:00:04 +0000, 2018-03-22 16:46:44 +0000]]