Another solution by testing if the string is encoded in Latin:
- for both strings, if the first character is a Latin (aka English) character
- if they are both, check if both begin with a letter or a number. In both cases, leave it
compare:
else, if you start with a number and a letter with the letter return NSOrderingAscending
, if the first with the letter is the first, otherwise NSOrderingDescending
If both strings are not Latin let compare:
solve again
- if it is Latin and one is not,
return NSOrderingAscending
, if Latin is the first, otherwise NSOrderingDescending
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 구 결
source share