Reputation:
I'm having a lot of problems with my code that determines the earliest date and latest date in an array. Here is the code I'm using:
NSDate *startDate = nil; // Earliest date
NSDate *endDate = nil; // Latest date
for (id entry in myArray)
{
NSDate *date = [entry objectForKey:kDate];
if (startDate == nil && endDate == nil)
{
startDate = date;
endDate = date;
}
else if ([date compare:endDate] == NSOrderedAscending)
{
startDate = date;
}
else if ([date compare:startDate] == NSOrderedDescending)
{
endDate = date;
}
date = nil;
}
Please can someone help me work out where I'm going wrong?
Upvotes: 5
Views: 4078
Reputation: 1242
The earliest date might be found by using the standard algorithm to fine min/max value in array:
NSMutableArray<NSDate *> *allDates; // dates array
NSDate *earliestDate = allDates.firstObject;
for (NSDate *date in allDates) {
if ([date compare:earliestDate] == NSOrderedAscending) {
earliestDate = date;
}
}
To find the latest date in array use NSOrderedDescending
instead of NSOrderedAscending
.
Upvotes: 0
Reputation: 387
Just for other similar problems: the valueForKeyPath:
option is very neat I think:
[myArray valueForKeyPath:@"@min.self"];
[myArray valueForKeyPath:@"@max.self"];
This assumes the object in the array implement the compare:
method the way you want it. I use it to get the earliest date in an array of dates for example. If you would like to use it here, the objects in the array should override the compare:
method though.
Upvotes: 0
Reputation: 540
Also you can sort NSArray
with NSDates
with method:
array = [array sortedArrayUsingSelector:@selector(compare:)];
Then at [array firstObject]
will be first date (e.g. 1970-01-01T00:00:00), and last object: [array lastObject]
will be last date: (e.g. 2011-01-12T00:00:00)
Upvotes: 11
Reputation: 17705
You could also use the earlierDate:
and laterDate:
NSDate functions
NSDate *startDate = [NSDate distantFuture]; NSDate *endDate = [NSDate distantPast]; for (id entry in myArray) { NSDate *date = [entry objectForKey:kDate]; startDate = [startDate earlierDate:date]; endDate = [endDate laterDate:date]; }
Upvotes: 2
Reputation: 119144
You may also use the pre-defined distantPast
and distantFuture
constants to avoid the extra check for nil
:
NSDate *startDate = [NSDate distantFuture];
NSDate *endDate = [NSDate distantPast];
for (id entry in myArray)
{
NSDate *date = [entry objectForKey:kDate];
if ([date compare:startDate] == NSOrderedAscending) { startDate = date; }
if ([date compare:endDate] == NSOrderedDescending) { endDate = date; }
date = nil;
}
Upvotes: 3
Reputation: 34912
Surely you're setting startDate
and endDate
the wrong way round in the else if
statements? Don't you want this:
NSDate *startDate = nil; // Earliest date
NSDate *endDate = nil; // Latest date
for (id entry in myArray)
{
NSDate *date = [entry objectForKey:kDate];
if (startDate == nil && endDate == nil)
{
startDate = date;
endDate = date;
}
if ([date compare:startDate] == NSOrderedAscending)
{
startDate = date;
}
if ([date compare:endDate] == NSOrderedDescending)
{
endDate = date;
}
date = nil;
}
Upvotes: 8