2009-10-25 9 views
17

Guardo nombres como claves y puntajes como valores en NSDictionary para guardar en NSUserDefaults. Luego quiero recuperar las claves ordenadas por puntaje, pero no puedo ordenarlas numéricamente, solo por cuerda. La lista de puntajes 100, 50, 300, 200, 500, por ejemplo, me da 100, 200, 300, 50, 500.NSTecla de identificación ordenada por valor numéricamente

¿Se puede hacer esto o debo hacerlo de otra manera?

NSString *defaultNames[] = {@"Matt", @"Terry",@"Jessica",@"Sean",nil}; 
NSNumber *defaultScores[] = {@"600", @"500",@"100",@"50", nil}; 

NSDictionary *newScoreDict = [NSDictionary dictionaryWithObjects:(id *)defaultScores forKeys:(id *)defaultNames count:7]; 

NSArray *currScores = [scoreDict keysSortedByValueUsingSelector:@selector(compare:)]; 
+3

cuerdas ¿Por qué estás poniendo en su matriz de punteros NSNumber? –

+0

esa es una excelente pregunta ... jeje, debo haberme perdido esa – Matt

+1

¿Por qué dices que hay 7 objetos en las matrices cuando realmente hay 4? –

Respuesta

2

-compare: es una cadena de comparación. Pasar un método diferente para la comparación, por ejemplo:

@implementation NSString (numericComparison) 

- (NSComparisonResult) compareNumerically:(NSString *) other 
{ 
float myValue = [self floatValue]; 
float otherValue = [other floatValue]; 
if (myValue == otherValue) return NSOrderedSame; 
return (myValue < otherValue ? NSOrderedAscending : NSOrderedDescending); 
} 

@end 

En su caso específico, se puede utilizar en lugar -intValue.

+0

Intentando escribir código similar a este pero no toma un NSString, en cambio toma un int.¿Qué hace [self floatValue]? ¿apunta a? – prince

0

No estoy seguro de que ayudaría, pero también puede guardar un NSArray en un plist; A diferencia de un NSDictionary (que devuelve las llaves en un orden esencialmente aleatorio), que los vuelvas a medida que los pone en.

7

cómo sobre el uso de keysSortedByValueUsingSelector (NSDictionary)

parece ser lo que necesita según la documentación de XCode

+0

solo disponible para 10.6+ – hmak

+2

@hmak: No. Debe haber estado pensando en 'keysSortedByValueUsingComparator:' La publicación menciona 'keysSortedByValueUsingSelector:', que ha estado disponible desde 10.0 – user102008

+1

¿Debo mencionar que la pregunta es para iOS y no para MacOS? –

3
@implementation NSString (numericComparison) 

- (NSComparisonResult) floatCompare:(NSString *) other 
{ 
    float myValue = [self floatValue]; 
    float otherValue = [other floatValue]; 
    if (myValue == otherValue) return NSOrderedSame; 
    return (myValue < otherValue ? NSOrderedAscending : NSOrderedDescending); 
} 

- (NSComparisonResult) intCompare:(NSString *) other 
{ 
    int myValue = [self intValue]; 
    int otherValue = [other intValue]; 
    if (myValue == otherValue) return NSOrderedSame; 
    return (myValue < otherValue ? NSOrderedAscending : NSOrderedDescending); 
} 

@end 

NSString *defaultNames[] = {@"Matt", @"Terry",@"Jessica",@"Sean",nil}; 
// NSNumber *defaultScores[] = {@"600", @"500",@"100",@"50", nil}; 

NSNumber *defaultScores[] = {                 
      [NSNumber numberWithInt:600], 
      [NSNumber numberWithInt:500], 
      [NSNumber numberWithInt:100], 
      [NSNumber numberWithInt:50], 
      nil 
    }; 

NSDictionary *newScoreDict = [NSDictionary dictionaryWithObjects:(id *)defaultScores forKeys:(id *)defaultNames count:4]; 

NSArray *currScores = [newScoreDict keysSortedByValueUsingSelector:@selector(intCompare:NotSureWhatGoesHere:)]; 

¿Todavía estoy confundido con la línea anterior?

No sólo tiene que utilizar

// 
NSArray *currScores = [newScoreDict keysSortedByValueUsingSelector:@selector(intCompare:other:)]; 
// 

es el conjunto de números de OK, o hay una manera más fácil?

muchas gracias ...

+0

¿Por qué está usando flotador en lugar de doble? – gnasher729

5
NSString *defaultNames[] = {@"Matt", @"Terry",@"Jessica",@"Sean",nil}; 
NSNumber *defaultScores[] = {@"600", @"500",@"100",@"50", nil}; 
NSDictionary *newScoreDict = [NSDictionary dictionaryWithObjects:(id *)defaultScores forKeys:(id *)defaultNames count:7]; 
NSArray *currScores = [scoreDict keysSortedByValueUsingSelector:@selector(localizedStandardCompare:)]; 
+0

No pude conseguir esto funcionando ya que mis valores eran NSNumbers. Pero utilicé este comparador y funcionó: https://stackoverflow.com/a/9708772/2057171 –

0

Creo forma más sencilla de esta cuestión está aprovechando comparador ..

NSString *defaultNames[] = {@"Matt", @"Terry",@"Jessica",@"Sean",nil}; 
NSNumber *defaultScores[] = {@(600), @(500),@(400),@(50), nil}; 
NSDictionary *newScoreDict = [NSDictionary dictionaryWithObjects:defaultNames  forKeys:defaultScores count:4]; 
NSArray *currScores = [newScoreDict keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
    if ([obj1 integerValue] > [obj2 integerValue]) { 
     return NSOrderedAscending; 
    }else{ 
     return NSOrderedDescending; 
    }}]; 

for (NSString *string in currScores) { 
    NSLog(@"%@",string); 
} 

probar este .. me di cuenta de que no podía de valor con alcance usando el objeto NSNumber así que si quieres alcanzar el valor del objeto que yo resolví con el cambio de tus NSNumber anota a NSString y conviértalos en números mientras haces el pedido. Se puede utilizar, como a continuación ..

NSString *defaultNames[] = {@"Matt", @"Terry",@"Jessica",@"Sean",nil}; 
NSString *defaultScores[] = {@"600", @"500",@"400",@"50", nil}; 
NSMutableDictionary *newScoreDict = [NSMutableDictionary dictionaryWithObjects:defaultScores forKeys:defaultNames count:4]; 

NSArray *currScores = [newScoreDict keysSortedByValueUsingComparator:^NSComparisonResult(id obj1, id obj2) { 
NSNumberFormatter *formatter = [[NSNumberFormatter alloc] init]; 
[formatter setNumberStyle:NSNumberFormatterDecimalStyle]; 
NSNumber *number1 = [formatter numberFromString:obj1]; 
NSNumber *number2 = [formatter numberFromString:obj2]; 
    if (number1.intValue > number2.intValue) { 
     return NSOrderedDescending; 
    }else{ 
     return NSOrderedAscending; 
    }}]; 

for (NSString *name in currScores) { 
    NSLog(@"key %@ value %@",name,[newScoreDict valueForKey:name]); 
} 

creo que sirve ..

Cuestiones relacionadas