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:)];
how about using keysSortedByValueUsingSelector (NSDictionary)
Seems to be what you need as per the documentation in XCode
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:)];
@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...
-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.
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.
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