6

I need to sort an NSArray containing time NSString's such as,

NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:@"09:00 AM",@"07:30 AM",@"06:45 PM",@"05:00 PM",@"12:45 AM",@"12:45 PM",@"01:00 AM",@"01:15 PM", nil];

What I need is to sort the array in ascending order of time.
Is there any way to do such a thing?

Chris Ballard
  • 3,771
  • 4
  • 28
  • 40
Guru
  • 4,693
  • 3
  • 25
  • 45
  • see this answer http://stackoverflow.com/questions/1132806/sort-nsarray-of-date-strings-or-objects/1134126#1134126 – Paras Joshi Apr 25 '13 at 07:18

4 Answers4

10
NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:@"09:00 AM",@"07:30 AM",@"06:45 PM",@"05:00 PM",@"12:45 AM",@"12:45 PM",@"01:00 AM",@"01:15 PM", nil];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"hh:mm a"];

NSArray *sortedTimes = [times sortedArrayUsingComparator:^NSComparisonResult(NSString *obj1, NSString *obj2)
{
    NSDate *date1 = [dateFormatter dateFromString:obj1];
    NSDate *date2 = [dateFormatter dateFromString:obj2];
    return [date1 compare:date2];
}];

optimized version:

NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:@"09:00 AM",@"07:30 AM",@"06:45 PM",@"05:00 PM",@"12:45 AM",@"12:45 PM",@"01:00 AM",@"01:15 PM", nil];

NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:@"hh:mm a"];

NSMutableArray *dates = [NSMutableArray arrayWithCapacity:times.count];
for (NSString *timeString in times)
{
    NSDate *date = [dateFormatter dateFromString:timeString];
    [dates addObject:date];
}

[dates sortUsingSelector:@selector(compare:)];

NSMutableArray *sortedTimes = [NSMutableArray arrayWithCapacity:dates.count];
for (NSDate *date in dates)
{
    NSString *timeString = [dateFormatter stringFromDate:date];
    [sortedTimes addObject:timeString];
}
filwag
  • 690
  • 5
  • 10
  • Added an edit. 2nd version seems to be better because with use less NSString/NSDate conversions there. – filwag Apr 25 '13 at 07:47
5

You can try this code:

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
    [formatter setDateFormat:@"hh:mm a"];
    [times sortUsingComparator:^NSComparisonResult(NSString* obj1, NSString *obj2) {
        NSDate *firstDate = [formatter dateFromString:obj1];
        NSDate *secondDate = [formatter dateFromString:obj2];
        return [firstDate compare:secondDate];
    }];
Satheesh
  • 10,998
  • 6
  • 50
  • 93
danypata
  • 9,895
  • 1
  • 31
  • 44
  • @satheeshwaran I'm new to SO, how can I highlight the code snippet like you did ? Thx. – danypata Apr 25 '13 at 07:39
  • Select what all text you want to move to code block and click on {} on the top, it is next to Bold, Italics buttons. – Satheesh Apr 25 '13 at 07:42
4

As these are strings it will be sored as

01:15, 12:25, 05:00....

And they are not either NSDate.

So you need to do is that Create a parallel array having NSDate from these strings, sort the array, and extract these values.


While implementing I solved it by novice-way

NSMutableArray *times = [[NSMutableArray alloc]initWithObjects:@"09:00 AM",@"07:30 AM",@"06:45 PM",@"05:00 PM",@"12:45 AM",@"12:45 PM",@"01:00 AM",@"01:15 PM", nil];

NSMutableArray *dates=[NSMutableArray new];

NSDateFormatter *dateFormatter=[NSDateFormatter new];
[dateFormatter setDateFormat:@"hh:mm a"];

for (NSString *stringDate in times) {
        NSDate *date=[dateFormatter dateFromString:stringDate];
        [dates addObject:date];
}

NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reverseOrder = [dates sortedArrayUsingDescriptors:descriptors];

[times removeAllObjects];
for (NSDate *date in reverseOrder) {
        NSString *string=[dateFormatter stringFromDate:date];
        [times addObject:string];
}

NSLog(@"%@",times);
Anoop Vaidya
  • 46,283
  • 15
  • 111
  • 140
  • 3
    reminds me how before the recent iOS developer portal redesign dates on "Device History" page were sorted alphabetically: http://i.imgur.com/3ePRr.png – Kreiri Apr 25 '13 at 07:24
1

For NSDate Comparison use this:

+ (BOOL)isDate:(NSDate *)date1 smallerThanAnotherDate:(NSDate *)date2
{
    NSDate* enddate = date1;
    NSDate* currentdate = date2;
    NSTimeInterval distanceBetweenDates = [enddate timeIntervalSinceDate:currentdate];
    double secondsInMinute = 60;
    NSInteger secondsBetweenDates = distanceBetweenDates / secondsInMinute;
    
    if (secondsBetweenDates <= 0)
        return YES;
    else
        return NO;
}

So If you do not want to convert your hours to NSDate do this alone it works for me

NSArray *sortedTimes =  [times sortedArrayUsingSelector:@selector(localizedStandardCompare:)];
Satheesh
  • 10,998
  • 6
  • 50
  • 93