How to group array of objects by date in swift?
This is my solution to group by date(just day, month and year):
let groupDic = Dictionary(grouping: arr) { (pendingCamera) -> DateComponents in
let date = Calendar.current.dateComponents([.day, .year, .month], from: (pendingCamera.date)!)
return date
}
How to group Arrays by Date in Swift?
You can use Calendar startOfDay
.
let cal = Calendar.current
let grouped = Dictionary(grouping: orders.results, by: { cal.startOfDay(for: $0.createdAt) })
How to group array of dates by months in swift?
Here's the code for a Playground
I think your structs should probably be Int
values for the months, as when you go to populate something like a tableview, it'll be a PITA to re-order months if you've got them as Strings
.
struct ScheduleDates {
var month: String
var dates: [Date]
}
Anyway, here's the extension I wrote based on what you provided. I frankly think you should return a dictionary with an Int as the key and an array of Dates as the value, but here's what you wanted...
I used Dictionary(grouping:by:)
to construct a dictionary from an array of dates.
extension Date {
static func dateDictionary(from arrayOfDates: [Date]) -> [String: [Date]] {
// declare a dictionary
return Dictionary(grouping: arrayOfDates) { date -> String in
// get the month as an int
let monthAsInt = Calendar.current.dateComponents([.month], from: date).month
// convert the int to a string...i think you probably want to return an int value and do the month conversion in your tableview or collection view
let monthName = DateFormatter().monthSymbols[(monthAsInt ?? 0) - 1]
// return the month string
return monthName
}
}
}
Here's a utility method I wrote to generate data while I figured out how to do it. If you're going to be in production, don't force unwrap stuff as I did here.
// Utility method to generate dates
func createDate(month: Int, day: Int, year: Int) -> Date? {
var components = DateComponents()
components.month = month
components.day = day
components.year = year
return Calendar.current.date(from: components)!
}
Below is how I generated an array of sample dates to experiment.
// generate array of sample dates
let dateArray: [Date] = {
let months = Array(1...12)
let days = Array(1...31)
let years = [2019]
var dateArray: [Date] = []
while dateArray.count < 100 {
let randomMonth = months.randomElement()
let randomDay = days.randomElement()
let randomYear = years.randomElement()
if let month = randomMonth,
let day = randomDay,
let year = randomYear,
let date = createDate(month: month,
day: day,
year: year) {
dateArray.append(date)
}
}
return dateArray
}()
let monthDictionary = Date.dateDictionary(from: dateArray)
var arrayOfStructs: [ScheduleDates] = []
monthDictionary.keys.forEach { key in
let scheduleDate = ScheduleDates(month: key,
dates: monthDictionary[key] ?? [])
arrayOfStruct.append(scheduleDate)
}
print(arrayOfStructs)
How to group array data based on Date item into a dictionary
Given we fix your example up somewhat (using String
as Date
example), you could simply pass over the elements in data
and add to (and optionally increase) the corresponding key-value pair in the dict.
struct Item {
let date: String
let amount: Double
}
let data = [Item(date: "2017.02.15", amount: 25),
Item(date: "2017.02.14", amount: 50),
Item(date: "2017.02.11", amount: 35),
Item(date: "2017.02.15", amount: 15)]
var dict: [String: Double] = [:]
for item in data {
dict[item.date] = (dict[item.date] ?? 0) + item.amount
}
print(dict) // ["2017.02.14": 50.0, "2017.02.15": 40.0, "2017.02.11": 35.0]
Group array of Swift dates by month
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]]
Related Topics
Submitting iOS App to App Store Application Identifier Invalid
Phonegap on iOS with Absolute Path Urls for Assets
Fonts Not Displaying in Interface Builder
Disable iOS Simulator 'Connect Hardware Keyboard' Programmatically
Usage of String.Range in Swift 3.0
Uicollectionviewcell Dynamic Height W/Two Dynamic Labels & Auto Layout
Convert Nsattributedstring into Data for Storage
Swift Regular Expression Format
Enforce Collectionview to Have Only 2 Rows
Nsdateformatter Returns Nil in Swift and iOS Sdk 8.0
How to Prevent a Remote Notification from Being Displayed
Get Version Number of iOS Universal Framework in Client
How to Write Output of Augraph to a File
Custom Scenekit Geometry in Swift on iOS Not Working But Equivalent Objective C Code Does
How to Convert String to Unicode(Utf-8) String in Swift
Draggesture on a VStack with Lot of Buttons, How to Detect When the Drag Is Inside a Button