2012-03-14 33 views
39

Tengo un NSMutableDictionary con valores enteros, y me gustaría obtener una matriz de las claves, ordenadas por sus respectivos valores ascendentes. Por ejemplo, con este diccionario:Obtener las claves de NSDictionary ordenadas por sus respectivos valores

mutableDict = { 
    "A" = 2, 
    "B" = 4, 
    "C" = 3, 
    "D" = 1, 
} 

Me gustaría terminar con la matriz ["D", "A", "C", "B"]. Mi diccionario real es mucho más grande que cuatro elementos, por supuesto.

+0

Hay docenas de elementos, que quieren un nuevo conjunto de teclas ordenados por los valores ascendentes de las teclas que contienen números enteros – Eric

+0

Josh, por lo que estoy tratando de hacer, sí que son todos los números enteros. Gracias por la ayuda de todos! – Eric

Respuesta

62

El método NSDictionarykeysSortedByValueUsingComparator: debería hacer el truco.

Solo necesita un método que devuelva un NSComparisonResult que compare los valores del objeto.

Su diccionario es

NSMutableDictionary * myDict; 

Y Array es

NSArray *myArray; 

myArray = [myDict keysSortedByValueUsingComparator: ^(id obj1, id obj2) { 

    if ([obj1 integerValue] > [obj2 integerValue]) { 

      return (NSComparisonResult)NSOrderedDescending; 
    } 
    if ([obj1 integerValue] < [obj2 integerValue]) { 

      return (NSComparisonResult)NSOrderedAscending; 
    } 

    return (NSComparisonResult)NSOrderedSame; 
}]; 

sólo tiene que utilizar NSNumber objetos en lugar de constantes numéricas.

Por cierto, esto se toma a partir de: https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/Collections/Articles/Dictionaries.html

+4

La propuesta de Richard es más elegante que la mía porque NSNumber ya viene con una función de comparación adecuada, pero la mía es probablemente más general. –

+1

En la mayoría de los casos, esta solución funcionará bien, pero lo que mi respuesta tiene es la capacidad de admitir otros tipos que responden al '-compare:' –

+0

Esto devolverá la lista de claves, ¿hay alguna forma que pueda obtener el diccionario directamente? en lugar de tener una lista de claves ordenadas en el conjunto –

26

NSDictionary tiene este método ordenado llamado allKeys.

Si quiere ordenar la matriz, keysSortedByValueUsingComparator: debería hacer el truco.

solución de Richard también funciona, pero hace algunas llamadas adicionales que no necesariamente necesita:

// Assuming myDictionary was previously populated with NSNumber values. 
NSArray *orderedKeys = [myDictionary keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2){ 
    return [obj1 compare:obj2]; 
}]; 
+0

Edité mi pregunta, pensé que estaba implícito que las claves tenían que estar ordenadas por el valor clave – Eric

+0

. Estoy pidiendo ayuda con la clasificación. – Eric

+0

'keysSortedByValueUsingComparator:' hará esta ordenación. –

14

he aquí una solución:

NSDictionary *dictionary; // initialize dictionary 
NSArray *sorted = [[dictionary allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
    return [[dictionary objectForKey:obj1] compare:[dictionary objectForKey:obj2]]; 
}]; 
+0

funciona correctamente para cadenas que comienzan con alphabates solamente, pero cuando hay una cadena que comienza con el número 10, comienza entre la primera cadena que comienza con "A" y la tercera cadena que comienza con "A" – ViruMax

+0

Compruebe la respuesta anterior, es más intuitiva y concisa , aunque esto hace lo mismo. – nemesis

13

La solución más simple:

[dictionary keysSortedByValueUsingSelector:@selector(compare:)]

+1

cómo escribir esa función de comparación –

+0

Por favor, explique el método de comparación también. – Tuhin

+0

Para los tipos existentes (por ejemplo, NSString), ese método ya existe. Para cualquier cosa que cree usted mismo, el método debe devolver NSOrderedAscending, NSOrderedSame o NSOrderedDescending, dependiendo del orden. Consulte la documentación de 'compare: options: range:' para obtener más información. – dgatwood

2

Aquí he hecho algo como esto:

NSMutableArray * weekDays = [[NSMutableArray alloc] initWithObjects:@"Sunday",@"Monday",@"Tuesday",@"Wednesday",@"Thursday",@"Friday",@"Saturday", nil]; 
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init]; 
NSMutableArray *dictArray = [[NSMutableArray alloc] init]; 

for(int i = 0; i < [weekDays count]; i++) 
{ 
    dict = [NSMutableDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:i],@"WeekDay",[weekDays objectAtIndex:i],@"Name",nil]; 
    [dictArray addObject:dict]; 
} 
NSLog(@"Before Sorting : %@",dictArray); 

@try 
{ 
    //for using NSSortDescriptor 
    NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"WeekDay" ascending:YES]; 
    NSArray *descriptor = @[sortDescriptor]; 
    NSArray *sortedArray = [dictArray sortedArrayUsingDescriptors:descriptor]; 
    NSLog(@"After Sorting : %@",sortedArray); 

    //for using predicate 
    //here i want to sort the value against weekday but only for WeekDay<=5 
    int count=5; 
    NSPredicate *Predicate = [NSPredicate predicateWithFormat:@"WeekDay <=%d",count]; 
    NSArray *results = [dictArray filteredArrayUsingPredicate:Predicate]; 

    NSLog(@"After Sorting using predicate : %@",results); 
} 
@catch (NSException *exception) 
{ 
    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Sorting cant be done because of some error" message:[NSString stringWithFormat:@"%@",exception] delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil]; 
    [alert setTag:500]; 
    [alert show]; 
    [alert release]; 
} 
Cuestiones relacionadas