Como classificar um NSArray em ordem alfabética?

375

Como posso ordenar uma matriz preenchida [UIFont familyNames]em ordem alfabética?

DotSlashSlash
fonte

Respostas:

725

A abordagem mais simples é fornecer um seletor de classificação ( documentação da Apple para obter detalhes)

Objetivo-C

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

Rápido

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

A Apple fornece vários seletores para classificação alfabética:

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

Rápido

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

Referência

Thomas Zoechling
fonte
5
O link da documentação está desatualizado, a amostra de código não é realmente suficiente para classificar a matriz. localizedCaseInsensitiveCompare: precisa ser definido de alguma forma.
M. Ryan
34
Eu atualizei o link. Obrigado por apontar isso. localizedCaseInsensitiveCompare: é um método de NSString e deve ser suficiente para classificar uma matriz de seqüências de caracteres.
Thomas Zoechling
11
E isso pode ser facilmente aplicado a uma matriz que contém objetos personalizados (não apenas NSString). Você só precisa garantir que todos os objetos dentro de sua matriz tenham implementado a mensagem que o seletor está especificando. Então, nesta mensagem, você chama a comparação NSString para as propriedades do seu objeto que você deseja comparar.
Lgdev 22/06/2012
Coisas simples assim não devem ser tão complexas.
Dmitry
276

As outras respostas fornecidas aqui mencionam o uso de @selector(localizedCaseInsensitiveCompare:) Isso funciona muito bem para uma matriz do NSString; no entanto, se você deseja estender isso para outro tipo de objeto e classificar esses objetos de acordo com a propriedade 'name', faça o seguinte:

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

Seus objetos serão classificados de acordo com a propriedade name desses objetos.

Se você deseja que a classificação não diferencie maiúsculas de minúsculas, defina o descritor como este

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
JP Hribovsek
fonte
14
+1, obrigado. Engraçado, esse é o caso de uso mais comum que a resposta aceita.
Vinay W
4
Isso classifica letras maiúsculas primeiro e depois letras pequenas
Harshit
+1, o descritor de classificação e o seletor são exatamente o que eu queria e nenhuma outra resposta teve isso. Muito obrigado cara
Ganesh Somani
11
Eu recebo um erro quando tento classificar uma matriz de seqüências de caracteres dessa maneira, porque namenão é uma chave válida. Qual chave eu uso para classificar seqüências de caracteres em ordem alfabética com um NSSortDescriptor?
temporary_user_name
27

Uma maneira mais poderosa de classificar uma lista de NSString para usar coisas como NSNumericSearch:

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

Combinado com SortDescriptor, isso daria algo como:

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
fonte
10

Use o código abaixo para classificar em ordem alfabética:

    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);

Abaixo está o log do console:

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
fonte
10

Outro método fácil de classificar uma matriz de seqüências consiste em usar a descriptionpropriedade NSString da seguinte maneira:

NSSortDescriptor *valueDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
arrayOfSortedStrings = [arrayOfNotSortedStrings sortedArrayUsingDescriptors:@[valueDescriptor]];
Lisarien
fonte
11
Isso parece um pouco inútil; não há razão para classificar as strings dessa maneira (e provavelmente há um impacto no desempenho para fazê-lo) e, para outros objetos, sua propriedade de descrição raramente é útil para fins de classificação.
mah
3

Isso já tem boas respostas para a maioria dos propósitos, mas vou adicionar o meu, que é mais específico.

Em inglês, normalmente quando alfabetizamos, ignoramos a palavra "the" no início de uma frase. Portanto, "Os Estados Unidos" seriam ordenados sob "U" e não "T".

Isso faz isso por você.

Provavelmente seria melhor colocá-los em categorias.

// 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
fonte
Eu olhei para isso anos mais tarde e percebi que deveria incluir também "a" e "an". Estes devem ser fáceis de adicionar.
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
fonte