2011-11-23 12 views
4

我有一個NSArrayController,我想對內容進行排序,這樣任何有英文字母的東西都會先排序,然後任何有數字和非英文字符的東西都會排在最後。如何按照字母順序排列數組控制器中最後一個在objective-c中的數字?

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

目前我只知道怎麼按字母順序排序。建議?

NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey:@"name" ascending:YES]; 
     [dataController setSortDescriptors: [NSArray arrayWithObject: sort]]; 

回答

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

+0

很不錯的。謝謝! – skantner

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; 
            }]; 
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

通過測試另一種解決方案中,如果字符串是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 
구 
결 
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]|;   
}]; 
相關問題