Reputation: 31283
There are two classes called Event
and Agenda
.
class Event {
let id: Int
var title: String
var allDay: Int = 0
let location: String
var description: String?
var startDate: NSDate!
var endDate: NSDate!
}
class Agenda {
var date: NSDate!
var events = [Event]()
}
And I have an array of these Event
objects.
I need to filter this events array out based on it's startDate
property.
For example say there are 11 events. (I'm only showing the startDates here)
2015-07-20
2015-07-21
2015-07-21
2015-07-22
2015-07-22
2015-07-22
2015-07-23
2015-07-23
2015-07-24
2015-07-24
2015-07-24
I need to filter this array and create an array of Agenda
objects. Like this.
+------------+----------------+
| date | events (count) |
+------------+----------------+
| 2015-07-20 | 1 |
| 2015-07-21 | 2 |
| 2015-07-22 | 3 |
| 2015-07-23 | 2 |
| 2015-07-24 | 3 |
+------------+----------------+
I tried iterating through the events array and do it like below.
public func filterByDate(events: [Event]) {
var agendas = [Agenda]()
for event in events {
if agendas.isEmpty {
var agenda = Agenda()
agenda.date = event.startDate!
agenda.events.append(event)
agendas.append(agenda)
} else {
let lastAgenda = agendas.last!
let lastEventOfLastAgenda = lastAgenda.events.last!
if isSameDate(date1: event.startDate!, date2: lastEventOfLastAgenda.startDate!) {
lastAgenda.events.append(event)
} else {
var agenda = Agenda()
agenda.date = event.startDate!
agenda.events.append(event)
agendas.append(agenda)
}
}
}
}
func isSameDate(#date1: NSDate, date2: NSDate) -> Bool {
let calendar = NSCalendar.currentCalendar()
let components: NSCalendarUnit = .CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear
let date1Components = calendar.components(components, fromDate: date1)
let date2Components = calendar.components(components, fromDate: date2)
let date1 = calendar.dateFromComponents(date1Components)!
let date2 = calendar.dateFromComponents(date2Components)!
let result = date1.compare(date2)
if result == NSComparisonResult.OrderedSame {
return true
}
return false
}
But the result I get is incorrect. I get 6 objects in the agendas
array. When I just iterate through it, I get the following output.
2015-07-20 - 1
2015-07-21 - 1
2015-07-21 - 2
2015-07-22 - 4
2015-07-24 - 1
2015-07-24 - 2
I can't figure out where it's going wrong. Any help would be appreciated.
By the way even if I get this method to work it's still very messy and not very Swift-like. Is there a more elegant way to do this in Swift?
Upvotes: 2
Views: 170
Reputation: 2400
Edit: I have further simplified this by adding an itit()
to the Agenda
class. I believe that this concisely does what you have asked (this is Swift 2 in Xcode 7 beta 4). It creates an array of Agenda
objects [Agenda]
called agendaArray
.
Assuming we have an array of Event
objects called eventArray
where Event
is declared as in your question.
Here is my solution:
var agendaArray = [Agenda]()
for date in Set(eventArray.filter{$0.startDate != nil}.map{$0.startDate}) {
agendaArray.append(Agenda(date: date, events: eventArray.filter({$0.startDate == date})))
} // populates [Agenda] for each unique date
Here is the modified Agenda
class:
class Agenda {
// ...
init(date: NSDate!, events: [Event]){
self.date = date
self.events = events
}
Quickly test it (first have to sort by date since resulting array has no fixed order):
// quickly test it
agendaArray = agendaArray.sort({ $0.date.compare($1.date) == NSComparisonResult.OrderedAscending }) // sort it by date
for eachAgenda in agendaArray {
print("\(eachAgenda.date)")
print("count = \(eachAgenda.events.count)")
}
Upvotes: 0
Reputation: 876
Try a more elegant way:
var events: [Event] = Your Event Array Here ...
var groupedDates: [NSDate: Int] = [:]
for event in events {
if let number = groupedDates[event.startDate] {
groupedDates[event.startDate] = number + 1
}else{
groupedDates[event.startDate] = 1
}
}
println(groupedDates)
Upvotes: 1