I have an array of strings (names)
and i would like to sort them like how the address book on the iphone sorts them
- eg: éli -> under E
- eg: àli -> under A
- eg: 4li -> under #
any suggestions?
I have an array of strings (names)
and i would like to sort them like how the address book on the iphone sorts them
any suggestions?
You need to perform a diacritic insensitive comparison against the strings. NSString
has a compare:options:
method with an option of NSDiacriticInsensitiveSearch
.
NSArray *array = [NSArray arrayWithObjects:@"éli", @"bob", @"earl", @"allen", @"àli", @"aaron", nil];
NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
}];
Edit:
Here is a full example that will section the results based on the first character diacritic insensitive. I put in a dictionary so you would need to keep track of the sorted keys on your own to display properly.
NSArray *array = [NSArray arrayWithObjects:@"éli", @"bob", @"earl", @"allen", @"àli", nil];
NSArray *sorted = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
}];
NSMutableDictionary *sectioned = [NSMutableDictionary dictionary];
NSString *firstChar = nil;
for(NSString *str in sorted)
{
//Ignore empty strings
if(![str length])continue;
NSMutableArray *names = nil;
//Compare the first character using diacritic insensitive search
if([str compare:firstChar options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch range:NSMakeRange(0, 1)] == NSOrderedSame)
{
names = [sectioned objectForKey:firstChar];
}
else
{
//decomposedStringWithCanonicalMapping is where the magic happens
//(it removes the accent mark)
firstChar = [[str decomposedStringWithCanonicalMapping] substringToIndex:1];
names = [NSMutableArray array];
[sectioned setObject:names forKey:firstChar];
}
[names addObject:str];
}
NSLog(@"sorted: %@", sorted);
//This is sectioned like the address app
NSLog(@"sectioned: %@", sectioned);
all lies within the compare:
method you will use as the selector of your sorting method and more importantly with the NSDiacriticInsensitiveSearch
option.
[[yourArray] sortedArrayUsingSelector:@selector(compareTheAddressBookWay:)];
Now you need to add the compareTheAddressBookWay:
method in a category
@implementation NSString (YourCategory)
- (NSComparisonResult) compareTheAddressBookWay:(NSString*)iString
{
return [self compare:iString
options:NSCaseInsensitiveSearch|NSDiacriticInsensitiveSearch
range:NSRangeFromString(self)
}
@end
!!Important!!:
Using sortedArrayUsingSelector:
will be compliant for iOS up to 2.0
while usingsortedArrayUsingComparator:
will ONLY work for iOS 4 and above.