2009-10-25 1 views
17

Я сохраняю имена как ключи и оценки как значения в NSDictionary для сохранения в NSUserDefaults. Затем я хочу вернуть ключи, отсортированные по счету, но я не могу сортировать их численно, только по строкам. Список баллов 100, 50, 300, 200, 500, например, дает мне 100, 200, 300, 50, 500.Клавиши NSDictionary, отсортированные по значению численно

Можно ли это сделать или мне нужно пойти по этому поводу по-другому?

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

Почему вы кладя строки в массив указателей NSNumber? –

+0

Это отличный вопрос ... хе-хе, я, должно быть, пропустил это – Matt

+1

Почему вы говорите, что в массивах есть 7 объектов, когда есть действительно 4? –

ответ

2

-compare: сравнение строк. Пропустите другой метод для сравнения, например:

@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 

В вашем конкретном случае, вы могли бы использовать вместо -intValue.

+0

Пытаясь написать код, похожий на этот, но не берет в NSString, вместо этого берет int.Что [self floatValue]; указать на? – prince

0

Не уверен, что это поможет, но вы также можете сохранить NSArray в plist; в отличие от NSDictionary (который возвращает ключи в существенно случайном порядке), вы получите их обратно, как вы поместите их в.

7

как об использовании keysSortedByValueUsingSelector (NSDictionary)

Кажется, что вам нужно в соответствии с документацией в XCode

+0

доступно только для 10.6+ – hmak

+2

@hmak: Нет. Вы, должно быть, думали о 'keysSortedByValueUsingComparator:' Сообщение упоминает 'keysSortedByValueUsingSelector:', который был доступен с 10.0 – user102008

+1

. Должен ли я упоминать, что вопрос касается iOS, а не 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:)]; 

Я все еще смущен предыдущей строкой?

ли я просто использовать

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

ли массив чисел OK, или есть более простой способ?

Большое спасибо ...

+0

Почему вы используете float вместо double? – 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

Я не мог получить эту работу, так как моими значениями были NSNumbers. Но я использовал этот компаратор, и он работал: https://stackoverflow.com/a/9708772/2057171 –

0

Я думаю, что самый простой способ этот вопрос с помощью компаратора ..

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

попробовать это .. я заметил, что я не мог значение рич с используя объект NSNumber, поэтому, если вы хотите достичь значения объекта, чем я решил, изменив ваши NSNumber-оценки на NSString и преобразуя их в числа при заказе. Вы можете использовать, как показано ниже ..

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

Надеется, что это помогает ..