Jak posortować alfabetycznie tablicę NSArray?

375

Jak mogę posortować tablicę wypełnioną [UIFont familyNames]w kolejności alfabetycznej?

DotSlashSlash
źródło

Odpowiedzi:

725

Najprostszym podejściem jest zapewnienie selektora sortowania ( szczegółowe informacje w dokumentacji Apple )

Cel C

sortedArray = [anArray sortedArrayUsingSelector:@selector(localizedCaseInsensitiveCompare:)];

Szybki

let descriptor: NSSortDescriptor = NSSortDescriptor(key: "YourKey", ascending: true, selector: "localizedCaseInsensitiveCompare:")
let sortedResults: NSArray = temparray.sortedArrayUsingDescriptors([descriptor])

Apple oferuje kilka selektorów do sortowania alfabetycznego:

  • compare:
  • caseInsensitiveCompare:
  • localizedCompare:
  • localizedCaseInsensitiveCompare:
  • localizedStandardCompare:

Szybki

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort()
print(students)
// Prints "["Abena", "Akosua", "Kofi", "Kweku", "Peter"]"

Odniesienie

Thomas Zoechling
źródło
5
Link do dokumentacji jest nieaktualny, przykładowy kod nie jest tak naprawdę wystarczający, aby posortować tablicę. localizedCaseInsensitiveCompare: należy jakoś zdefiniować.
M. Ryan,
34
Zaktualizowałem link. Dzięki za zwrócenie na to uwagi. localizedCaseInsensitiveCompare: jest metodą NSString i powinna wystarczyć do sortowania tablicy ciągów.
Thomas Zoechling,
1
Można to łatwo zastosować do tablicy zawierającej dowolne obiekty niestandardowe (nie tylko NSString). Musisz tylko upewnić się, że wszystkie obiekty w tablicy zaimplementowały komunikat, który określa selektor. Następnie w tym komunikacie po prostu wywołujesz porównanie NSString dla właściwości obiektu, który chcesz porównać.
lgdev
Takie proste rzeczy nie mogą być tak skomplikowane.
Dmitry
276

Inne podane tu odpowiedzi wspominają o użyciu @selector(localizedCaseInsensitiveCompare:) To działa świetnie dla tablicy NSString, jednak jeśli chcesz rozszerzyć to na inny typ obiektu i posortować te obiekty według właściwości „name”, powinieneś to zrobić zamiast tego:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES];
sortedArray=[anArray sortedArrayUsingDescriptors:@[sort]];

Twoje obiekty zostaną posortowane według właściwości nazwy tych obiektów.

Jeśli chcesz, aby sortowanie nie uwzględniało wielkości liter, musisz ustawić taki deskryptor w ten sposób

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
JP Hribovsek
źródło
14
+1, dziękuję Zabawne, że jest to częstszy przypadek użycia niż zaakceptowana odpowiedź.
Vinay W,
4
sortuje najpierw wielkie, a potem małe litery
HarshIT
+1, Deskryptor sortowania wraz z selektorem jest dokładnie tym, czego chciałem i żadna inna odpowiedź tego nie miała. Wielkie dzięki, człowieku
Ganesh Somani
1
Występuje błąd, gdy próbuję posortować tablicę ciągów w ten sposób, ponieważ namenie jest to prawidłowy klucz. Jakiego klucza używam do sortowania ciągów alfabetycznie za pomocą NSSortDescriptor?
tymczasowego
27

Bardziej wydajny sposób sortowania listy NSString w celu użycia takich rzeczy jak NSNumericSearch:

NSArray *sortedArrayOfString = [arrayOfString sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
            return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
        }];

W połączeniu z SortDescriptor dałoby to coś takiego:

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES comparator:^NSComparisonResult(id obj1, id obj2) {
        return [(NSString *)obj1 compare:(NSString *)obj2 options:NSNumericSearch];
    }];
NSArray *sortedArray = [anArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
Ben G.
źródło
10

Użyj poniższego kodu do sortowania w kolejności alfabetycznej:

    NSArray *unsortedStrings = @[@"Verdana", @"MS San Serif", @"Times New Roman",@"Chalkduster",@"Impact"];

    NSArray *sortedStrings =
    [unsortedStrings sortedArrayUsingSelector:@selector(compare:)];

    NSLog(@"Unsorted Array : %@",unsortedStrings);        
    NSLog(@"Sorted Array : %@",sortedStrings);

Poniżej znajduje się dziennik konsoli:

2015-04-02 16:17:50.614 ToDoList[2133:100512] Unsorted Array : (
    Verdana,
    "MS San Serif",
    "Times New Roman",
    Chalkduster,
    Impact
)

2015-04-02 16:17:50.615 ToDoList[2133:100512] Sorted Array : (
    Chalkduster,
    Impact,
    "MS San Serif",
    "Times New Roman",
    Verdana
)
Jayprakash Dubey
źródło
10

Inna łatwa metoda sortowania tablicy ciągów polega na użyciu descriptionwłaściwości NSString w ten sposób:

NSSortDescriptor *valueDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
arrayOfSortedStrings = [arrayOfNotSortedStrings sortedArrayUsingDescriptors:@[valueDescriptor]];
Lisarien
źródło
1
To wydaje się trochę bezużyteczne; nie ma powodu, aby sortować ciągi w ten sposób (i prawdopodobnie jest to efekt wydajności), a dla innych obiektów jego właściwość opisu rzadko jest przydatna do celów sortowania.
mah
3

To już ma dobre odpowiedzi na większość celów, ale dodam moje, które jest bardziej szczegółowe.

W języku angielskim, zwykle alfabetycznie, ignorujemy słowo „the” na początku frazy. Tak więc „Stany Zjednoczone” byłyby zamawiane pod „U”, a nie „T”.

To dla ciebie.

Prawdopodobnie najlepiej byłoby umieścić je w kategoriach.

// Sort an array of NSStrings alphabetically, ignoring the word "the" at the beginning of a string.

-(NSArray*) sortArrayAlphabeticallyIgnoringThes:(NSArray*) unsortedArray {

    NSArray * sortedArray = [unsortedArray sortedArrayUsingComparator:^NSComparisonResult(NSString* a, NSString* b) {

        //find the strings that will actually be compared for alphabetical ordering
        NSString* firstStringToCompare = [self stringByRemovingPrecedingThe:a];
        NSString* secondStringToCompare = [self stringByRemovingPrecedingThe:b];

        return [firstStringToCompare compare:secondStringToCompare];
    }];
    return sortedArray;
}

// Remove "the"s, also removes preceding white spaces that are left as a result. Assumes no preceding whitespaces to start with. nb: Trailing white spaces will be deleted too.

-(NSString*) stringByRemovingPrecedingThe:(NSString*) originalString {
    NSString* result;
    if ([[originalString substringToIndex:3].lowercaseString isEqualToString:@"the"]) {
        result = [[originalString substringFromIndex:3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
    else {
        result = originalString;
    }
    return result;
}
narco
źródło
Właśnie spojrzałem na te lata później i zdałem sobie sprawę, że powinno ono również zawierać „a” i „an”. Powinny być łatwe do dodania.
narco
1
-(IBAction)SegmentbtnCLK:(id)sender
{ [self sortArryofDictionary];
    [self.objtable reloadData];}
-(void)sortArryofDictionary
{ NSSortDescriptor *sorter;
    switch (sortcontrol.selectedSegmentIndex)
    {case 0:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Name" ascending:YES];
            break;
        case 1:
            sorter=[[NSSortDescriptor alloc]initWithKey:@"Age" ascending:YES];
            default:
            break; }
    NSArray *sortdiscriptor=[[NSArray alloc]initWithObjects:sorter, nil];
    [arr sortUsingDescriptors:sortdiscriptor];
    }
deepa
źródło