如何使用objective-c中的数字按字母顺序对数组控制器进行排序?

Dav*_*vid 4 sorting cocoa objective-c nssortdescriptor

我有一个NSArrayController并且我想对内容进行排序,以便首先对具有英文字母的任何内容进行排序,然后对具有数字和非英文字符的任何内容进行排序.

例如:A,B,C ...... Z,1,2,3 ... 9,구,결,......

目前我只知道如何按字母顺序对项目进行排序.建议?

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES];
        [dataController setSortDescriptors: [NSArray arrayWithObject: sort]];
Run Code Online (Sandbox Code Playgroud)

djr*_*ero 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];         
}];
Run Code Online (Sandbox Code Playgroud)

要将英文字符放在英文字符之前,它就足以NSDiacriticInsensitiveSearch | NSCaseInsensitiveSearch作为选项使用,不需要花哨的算法.

如果你需要支持iOS而不用块试试sortedArrayUsingSelector.


Vik*_*ica 5

通过测试另一个解决方案,如果字符串是 latin1 可编码的:

\n\n
    \n
  • 测试两个字符串,如果第一个字符是拉丁(又名英语)字符
  • \n
  • 如果两者都是,则测试两者是否以字母或数字开头。在这两种情况下,将其保留在compare:
  • \n
  • 否则,如果一个以数字开头,一个以字母开头,return NSOrderingAscending则 ,如果以字母开头,则为第一个,否则NSOrderingDescending

  • \n
  • 如果两个字符串都不是拉丁字符串,请compare:再次决定

  • \n
  • 如果一个是拉丁文,一个不是,return NSOrderingAscending如果拉丁文在前,否则NSOrderingDescending
  • \n
\n\n

代码

\n\n
NSArray *array = [NSArray arrayWithObjects:@"peach",@"apple",@"7",@"banana",@"ananas",@"5", @"papaya",@"4",@"\xea\xb5\xac",@"\xea\xb2\xb0",@"1" ,nil];\n\narray = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {\n    NSString *s1 = [obj1 substringToIndex:1];\n    NSString *s2 = [obj2 substringToIndex:1];\n    BOOL b1 = [s1 canBeConvertedToEncoding:NSISOLatin1StringEncoding];\n    BOOL b2 = [s2 canBeConvertedToEncoding:NSISOLatin1StringEncoding];\n\n    if ((b1 == b2) && b1) {//both number or latin char\n        NSRange r1 = [s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];\n        NSRange r2 = [s2 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]];\n        if (r1.location == r2.location ) { // either both start with a number or both with a letter\n            return [obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch]; \n        } else {  // one starts wit a letter, the other with a number\n            if ([s1 rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location == NSNotFound) {\n                return NSOrderedAscending;\n            }\n            return NSOrderedDescending;\n        }\n    } else if((b1 == b2) && !b1){ // neither latin char\n        return [obj1 compare:obj2 options:NSDiacriticInsensitiveSearch|NSCaseInsensitiveSearch];\n    } else { //one is latin char, other not\n        if (b1) return NSOrderedAscending;\n        return NSOrderedDescending;\n    }\n\n}];\nfor (NSString *s in array) NSLog(@"%@", s);\n
Run Code Online (Sandbox Code Playgroud)\n\n

结果

\n\n
ananas\napple\nbanana\npapaya\npeach\n1\n4\n5\n7\n\xea\xb5\xac\n\xea\xb2\xb0\n
Run Code Online (Sandbox Code Playgroud)\n