NSDictionary ключи отсортированы по значению в числовом - PullRequest
18 голосов
/ 25 октября 2009

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

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

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

Ответы [ 6 ]

7 голосов
/ 07 января 2010

как насчет использования keysSortedByValueUsingSelector (NSDictionary)

Похоже, что вам нужно согласно документации в XCode

5 голосов
/ 16 августа 2012
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:)];
3 голосов
/ 04 марта 2010
@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:)];
//

Массив чисел в порядке или есть более простой способ?

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

2 голосов
/ 25 октября 2009

-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 голосов
/ 30 мая 2014

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

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

Надеюсь, это поможет ..

0 голосов
/ 26 октября 2009

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

...