¿Cómo ordenar un NSArray alfabéticamente?

375

¿Cómo puedo ordenar una matriz llena [UIFont familyNames]en orden alfabético?

DotSlashSlash
fuente

Respuestas:

725

El enfoque más simple es proporcionar un selector de clasificación ( documentación de Apple para más detalles)

C objetivo

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

Rápido

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

Apple ofrece varios selectores para la clasificación 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"]"

Referencia

Thomas Zoechling
fuente
55
El enlace de documentación está desactualizado, la muestra de código no es realmente suficiente para ordenar la matriz. localizedCaseInsensitiveCompare: debe definirse de alguna manera.
M. Ryan
34
Actualicé el enlace. Gracias por señalar eso. localizedCaseInsensitiveCompare: es un método de NSString y debería ser suficiente para ordenar una serie de cadenas.
Thomas Zoechling
1
Y esto se puede aplicar fácilmente a una matriz que contiene cualquier objeto personalizado (no solo NSString). Solo tiene que asegurarse de que todos los objetos dentro de su matriz hayan implementado el mensaje que el selector está especificando. Luego, dentro de este mensaje, simplemente llame a la comparación NSString para conocer las propiedades de su objeto que desea comparar.
lgdev
Tales cosas simples no deben ser tan complejas.
Dmitry
276

Las otras respuestas proporcionadas aquí mencionan el uso de @selector(localizedCaseInsensitiveCompare:) Esto funciona muy bien para una matriz de NSString, sin embargo, si desea extender esto a otro tipo de objeto y ordenar esos objetos de acuerdo con una propiedad 'nombre', debe hacer esto en su lugar:

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

Sus objetos se ordenarán de acuerdo con la propiedad de nombre de esos objetos.

Si desea que la clasificación no distinga entre mayúsculas y minúsculas, deberá configurar el descriptor de esta manera

NSSortDescriptor *sort = [NSSortDescriptor sortDescriptorWithKey:@"name" ascending:YES selector:@selector(caseInsensitiveCompare:)];
JP Hribovsek
fuente
14
+1, gracias. Es curioso que este sea el caso de uso más común que la respuesta aceptada.
Vinay W
44
esto ordena las letras mayúsculas primero y luego las minúsculas
HarshIT
+1, el descriptor de clasificación junto con el selector es exactamente lo que quería y ninguna otra respuesta tenía esto. Muchas gracias hombre
Ganesh Somani
1
Me da un error cuando intento ordenar una serie de cadenas de esta manera, porque nameno es una clave válida. ¿Qué clave utilizo para ordenar las cadenas alfabéticamente con un NSSortDescriptor?
temporary_user_name
27

Una forma más poderosa de ordenar una lista de NSString para usar cosas como NSNumericSearch:

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

Combinado con SortDescriptor, eso daría 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
fuente
10

Use el siguiente código para ordenar en orden alfabético:

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

A continuación se muestra el registro de la consola:

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

Otro método fácil para ordenar una matriz de cadenas consiste en utilizar la descriptionpropiedad NSString de esta manera:

NSSortDescriptor *valueDescriptor = [NSSortDescriptor sortDescriptorWithKey:@"description" ascending:YES];
arrayOfSortedStrings = [arrayOfNotSortedStrings sortedArrayUsingDescriptors:@[valueDescriptor]];
Lisarien
fuente
1
Eso parece un poco inútil; no hay razón para ordenar las cadenas de esta manera (y probablemente haya un impacto en el rendimiento para hacerlo), y para otros objetos, su propiedad de descripción rara vez es útil para fines de clasificación.
mah
3

Esto ya tiene buenas respuestas para la mayoría de los propósitos, pero agregaré la mía, que es más específica.

En inglés, normalmente cuando alfabetizamos, ignoramos la palabra "the" al comienzo de una frase. Entonces "Estados Unidos" se ordenaría bajo "U" y no "T".

Esto hace eso por ti.

Probablemente sería mejor ponerlos en categorías.

// 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
fuente
Acabo de ver esto años más tarde, y me di cuenta de que también debería incluir "a" y "an". Estos deberían ser fáciles de agregar.
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
fuente