Another solution by testing, if a string is latin1-encodeable:
- test for both strings, if the first character is a latin (aka english) character
- if both are, test if both starts either with a letter or a number. In both cases, leave it up the
compare:
else, if one starts with the number and one with a letter, return NSOrderingAscending
, if the one with letter its first, otherwise NSOrderingDescending
If both strings aren't latin, let compare:
decide again
- if one is latin, and one not,
return NSOrderingAscending
if the latin is first, otherwise NSOrderingDescending
the code
NSArray *array = [NSArray arrayWithObjects:@"peach",@"apple",@"7",@"banana",@"ananas",@"5", @"papaya",@"4",@"구",@"결",@"1" ,nil];
array = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
NSString *s1 = [obj1 substringToIndex:1];
NSString *s2 = [obj2 substringToIndex:1];
BOOL b1 = [s1 canBeConvertedToEncoding:NSISOLatin1StringEncoding];
BOOL b2 = [s2 canBeConvertedToEncoding:NSISOLatin1StringEncoding];
if ((b1 == b2) && b1) {//both number or latin char
NSRange r1 = [s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
NSRange r2 = [s2 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];
if (r1.location == r2.location ) { // either both start with a number or both with a letter
return [obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
} else { // one starts wit a letter, the other with a number
if ([s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location == NSNotFound) {
return NSOrderedAscending;
}
return NSOrderedDescending;
}
} else if((b1 == b2) && !b1){ // neither latin char
return [obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
} else { //one is latin char, other not
if (b1) return NSOrderedAscending;
return NSOrderedDescending;
}
}];
for (NSString *s in array) NSLog(@"%@", s);
result
ananas
apple
banana
papaya
peach
1
4
5
7
구
결