¿Cómo clasifico un NSMutableArray con objetos personalizados?

Resuelto rustyshelf asked hace 54 años • 27 respuestas

Lo que quiero hacer parece bastante simple, pero no encuentro ninguna respuesta en la web. Tengo una NSMutableArrayserie de objetos y digamos que son objetos de 'Persona'. Quiero ordenar NSMutableArraypor Person.birthDate, que es un archivo NSDate.

Creo que tiene algo que ver con este método:

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(???)];

En Java haría que mi objeto implementara Comparable, o usaría Collections.sort con un comparador personalizado en línea... ¿cómo diablos se hace esto en Objective-C?

rustyshelf avatar Jan 01 '70 08:01 rustyshelf
Aceptado

método de comparación

O implementas un método de comparación para tu objeto:

- (NSComparisonResult)compare:(Person *)otherObject {
    return [self.birthDate compare:otherObject.birthDate];
}

NSArray *sortedArray = [drinkDetails sortedArrayUsingSelector:@selector(compare:)];

NSSortDescriptor (mejor)

o generalmente incluso mejor:

NSSortDescriptor *sortDescriptor;
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"birthDate"
                                           ascending:YES];
NSArray *sortedArray = [drinkDetails sortedArrayUsingDescriptors:@[sortDescriptor]];

Puede ordenar fácilmente por varias claves agregando más de una a la matriz. También es posible utilizar métodos de comparación personalizados. Eche un vistazo a la documentación .

Bloques (¡brillantes!)

También existe la posibilidad de ordenar con un bloque desde Mac OS X 10.6 e iOS 4:

NSArray *sortedArray;
sortedArray = [drinkDetails sortedArrayUsingComparator:^NSComparisonResult(Person *a, Person *b) {
    return [a.birthDate compare:b.birthDate];
}];

Actuación

Los -compare:métodos basados ​​en bloques serán bastante más rápidos, en general, que su uso, NSSortDescriptorya que este último se basa en KVC. La principal ventaja del NSSortDescriptormétodo es que proporciona una forma de definir el orden de clasificación utilizando datos, en lugar de código, lo que facilita, por ejemplo, configurar las cosas para que los usuarios puedan ordenar NSTableViewhaciendo clic en la fila del encabezado.

Georg Schölly avatar Apr 30 '2009 06:04 Georg Schölly

Ver el NSMutableArraymétodosortUsingFunction:context:

Necesitará configurar una función de comparación que tome dos objetos (de tipo Person, ya que está comparando dos Personobjetos) y un parámetro de contexto .

Los dos objetos son sólo ejemplos de Person. El tercer objeto es una cadena, por ejemplo @"birthDate".

Esta función devuelve un NSComparisonResult: Devuelve NSOrderedAscendingsi PersonA.birthDate< PersonB.birthDate. Volverá NSOrderedDescendingsi PersonA.birthDate> PersonB.birthDate. Finalmente, volverá NSOrderedSamesi PersonA.birthDate== PersonB.birthDate.

Este es un pseudocódigo aproximado; necesitarás desarrollar lo que significa que una fecha sea "menos", "más" o "igual" que otra fecha (como comparar segundos desde la época, etc.):

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  if ([firstPerson birthDate] < [secondPerson birthDate])
    return NSOrderedAscending;
  else if ([firstPerson birthDate] > [secondPerson birthDate])
    return NSOrderedDescending;
  else 
    return NSOrderedSame;
}

Si quieres algo más compacto, puedes usar operadores ternarios:

NSComparisonResult compare(Person *firstPerson, Person *secondPerson, void *context) {
  return ([firstPerson birthDate] < [secondPerson birthDate]) ? NSOrderedAscending : ([firstPerson birthDate] > [secondPerson birthDate]) ? NSOrderedDescending : NSOrderedSame;
}

La inserción en línea quizás podría acelerar esto un poco, si lo haces con frecuencia.

Alex Reynolds avatar Apr 30 '2009 06:04 Alex Reynolds