Подтвердить что ты не робот

Классы NSDictionary отсортированы по численному значению

Я сохраняю имена как ключи и оценки как значения в 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:)];
4b9b3361

Ответ 1

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

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

Ответ 2

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

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

Является ли массив чисел ОК, или есть более простой способ?

Спасибо, очень много...

Ответ 4

-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.

Ответ 5

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

Ответ 6

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

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

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