Reputation: 9324
I have a NSMutableArray with dictionaries, all of the dict's contain a NSDate is form of NSString with key 'Date'. I want to sort the NSDictionaries by the Dates. So for example i have the following state of the array:
Dict
Date
20.06.1996 23:30
Dict
Date
04.10.2011 19:00
Dict
Date
20.06.1956 23:39
And I want to sort it, so that it looks like this:
Dict
Date
20.06.1956 23:39
Dict
Date
20.06.1996 23:30
Dict
Date
04.10.2011 19:00
I have already experimented with NSSortDescriptor, but without success...
Update:
I have managed to sort the dates, but I came to this problem: In the dicts there is not only dates, also other objects, and what my code does is it only switches the date values between the dicts, instead of switching the complete dicts around. With this, the other values in the dicts get assigned a wrong date, which is very bad. Can anybody help me? Heres my code:
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"savedData.daf"];
NSMutableArray *d = [NSMutableArray arrayWithContentsOfFile:path];
for (int ii = 0; ii < [d count]; ii++) {
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
if (is24h) {
[dateFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
}
else {
[dateFormatter setDateFormat:@"dd.MM.yyyy hh:mm a"];
}
[dateFormatter setLocale:[NSLocale currentLocale]];
NSDate *dat = [dateFormatter dateFromString:[[d valueForKey:@"Date"] objectAtIndex:ii]];
NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
NSDictionary *oldDict = (NSDictionary *)[d objectAtIndex:ii];
[newDict addEntriesFromDictionary:oldDict];
[newDict setObject:dat forKey:@"Date"];
[d replaceObjectAtIndex:ii withObject:newDict];
[newDict release];
}
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:@"Date" ascending:YES];
NSArray *sorters = [[NSArray alloc] initWithObjects:sorter, nil];
[sorter release];
NSMutableArray *sorted = [NSMutableArray arrayWithArray:[d sortedArrayUsingDescriptors:sorters]];
[sorters release];
NSLog(@"%@",sorted);
for (int ii = 0; ii < [sorted count]; ii++) {
NSDateFormatter* dateFormatter = [[NSDateFormatter alloc] init];
if (is24h) {
[dateFormatter setDateFormat:@"dd.MM.yyyy HH:mm"];
}
else {
[dateFormatter setDateFormat:@"dd.MM.yyyy hh:mm a"];
}
[dateFormatter setLocale:[NSLocale currentLocale]];
NSString *sr = [dateFormatter stringFromDate:[[sorted valueForKey:@"Date"] objectAtIndex:ii]];
NSMutableDictionary *newDict = [[NSMutableDictionary alloc] init];
NSDictionary *oldDict = (NSDictionary *)[d objectAtIndex:ii];
[newDict addEntriesFromDictionary:oldDict];
[newDict setObject:sr forKey:@"Date"];
[sorted replaceObjectAtIndex:ii withObject:newDict];
[newDict release];
}
NSLog(@"before: %@"
""
"after: %@",d,sorted);
[sorted writeToFile:path atomically:YES];
Upvotes: 2
Views: 3868
Reputation: 112857
There are a couple of options, one is to put NSDate objects in the dictionary.
One problem with comparing the strings is that you can 't just do a string compare because the year is not in the most significant potion of the string.
So, you will need to write a comparison method to use with:
- (NSArray *)sortedArrayUsingComparator:(NSComparator)cmptr
or perhaps:
- (NSArray *)sortedArrayUsingFunction:(NSInteger (*)(id, id, void *))comparator context:(void *)context
The comparator will need to handle the dd.mm.yyyy hh:mm
string format.
Other options include adding another dictionary key with an NSDate representation and sorting on that.
Upvotes: 0
Reputation: 113310
There are many ways to do this, one would be to use NSDate objects instead of NSStrings (or NSStrings formatted according to ISO 8601, so that the lexicographic sort would match the desired sorting). Then you could do:
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:@"Date"
ascending:YES];
[array sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
Or, if you can't (or don't want to) change your data, you can always sort using a block:
[array sortUsingComparator:^(id dict1, id dict2) {
NSDate *date1 = // create NSDate from dict1's Date;
NSDate *date2 = // create NSDate from dict2's Date;
return [date1 compare:date2];
}];
Of course this would probably be slower than the first approach since you'll usually end up creating more than n NSDate objects.
Upvotes: 12