我有一个NSArrayController
,我想对内容进行排序,以便首先对带有英文字母的任何内容进行排序,然后对包含数字和非英文字符的任何内容进行排序。
例如:A,B,C ...... Z,1,2,3 ... 9,구,결,......
目前我只知道如何按字母顺序对项目进行排序。建议?
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
[dataController setSortDescriptors: [NSArray arrayWithObject: sort]];
答案 0 :(得分:10)
您可以使用sortedArrayUsingComparator
根据需要自定义排序算法。例如,您可以使用以下行标记优先级:
NSArray *assorted = [@"1 2 3 9 ; : 구 , 결 A B C Z ! á" componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *sorted = [assorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
/* NSOrderedAscending, NSOrderedSame, NSOrderedDescending */
BOOL isPunct1 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj1 characterAtIndex:0]];
BOOL isPunct2 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj2 characterAtIndex:0]];
if (isPunct1 && !isPunct2) {
return NSOrderedAscending;
} else if (!isPunct1 && isPunct2) {
return NSOrderedDescending;
}
return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];
}];
要在非英语之前放置英语字符,使用NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch
作为选项就足够了,不需要花哨的算法。
如果您需要支持不带阻止的iOS,请尝试sortedArrayUsingSelector
。
答案 1 :(得分:4)
测试的另一个解决方案,如果字符串是latin1-encodeable:
compare:
否则,如果一个以数字开头,另一个以字母return NSOrderingAscending
开头,如果是第一个字母,则为NSOrderingDescending
如果两个字符串都没有拉丁语,请compare:
再次决定
return NSOrderingAscending
如果拉丁语是第一个,否则NSOrderingDescending
代码
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);
结果
ananas
apple
banana
papaya
peach
1
4
5
7
구
결
答案 2 :(得分:3)
我不认为你可以在没有定义自己的比较功能的情况下进行那种排序。
为此,您可以使用sortedArrayUsingFunction:
[array sortedArrayUsingFunction:f context:userContext];
其中f定义为:
NSInteger f(id num1, id num2, void *context)
{
int v1 = [num1 intValue];
int v2 = [num2 intValue];
if (...)
return NSOrderedAscending;
else if (...)
return NSOrderedDescending;
else
return NSOrderedSame;
}
如果您不想为此创建函数,可以使用方法的块版本sortedArrayUsingComparator:
[array sortedArrayUsingComparator: ^(id obj1, id obj2) {
return NSOrderedSame;
}];
答案 3 :(得分:1)
基于比较器的排序描述符应该起作用(注意:未测试)。
NSComparator cmp = ^(id str1, id str2) {
// Make your sorting
if ( /* str1 before str2 */ )
return NSOrderedAscending
else if ( /* str2 after str1 */ )
return NSOrderedDescending
else
return NSOrderedSame
};
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey: sortKey ascending: YES comparator: cmp];
NSArrayController *ac = // ...
[ac setSortDescriptor: sd];
您当然必须定义自己的排序顺序算法 - 但此示例应显示如何为数组控制器使用排序描述符。
答案 4 :(得分:0)
缺少一件事来正确回答问题:NSNumericSearch
NSArray *assorted = [@"1 2 3 9 ; : 구 , 결 A B C Z ! á" componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
NSArray *sorted = [assorted sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
/* NSOrderedAscending, NSOrderedSame, NSOrderedDescending */
BOOL isPunct1 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj1 characterAtIndex:0]];
BOOL isPunct2 = [[NSCharacterSet punctuationCharacterSet] characterIsMember:[(NSString*)obj2 characterAtIndex:0]];
if (isPunct1 && !isPunct2) {
return NSOrderedAscending;
} else if (!isPunct1 && isPunct2) {
return NSOrderedDescending;
}
return [(NSString*)obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch|NSNumericSearch]|;
}];