NSDictionary keys sorted by value numerically

旧城冷巷雨未停 提交于 2019-11-27 03:55:41

问题


I store names as keys and scores as values into an NSDictionary for saving in NSUserDefaults. I then want to get back the keys sorted by score, but I can't seem to sort them numerically, only by string. The list of scores 100, 50, 300, 200, 500, for example, gives me 100, 200, 300, 50, 500.

Can this be done or do I need to go about this differently?

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

回答1:


how about using keysSortedByValueUsingSelector (NSDictionary)

Seems to be what you need as per the documentation in 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:)];

I am still confused with the previous line ?

Do I just use

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

Is the array of numbers OK, or is there an easier way ?

Thank You Very Much...




回答4:


-compare: is a string compare. Pass a different method for the comparison, e.g:

@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

In your specific case, you could use -intValue instead.




回答5:


Not sure it would help, but you can also save an NSArray in a plist; unlike an NSDictionary (which returns keys in essentially random order), you get them back as you put them in.




回答6:


I think simplest way of this question is using comparator..

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

try this.. I noticed that i couldnt reach value with using NSNumber object so if you want to reach object value than i solved with changing your NSNumber scores to NSString and convert them to numbers while ordering. You can use like below..

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

Hope it helps..



来源:https://stackoverflow.com/questions/1620001/nsdictionary-keys-sorted-by-value-numerically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!