Reputation: 858
I am trying to sort the keys of an NSMutableDictionary
with their respective values (values in ascending order). My code snippet is as follows:
NSArray *sortedKeysWithValues = [[myDict allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
return [[myDict objectForKey:obj2] compare:[myDict objectForKey:obj1]];}];
The contents of the NSMutableDictionary
are:
{
806: "-89.06";
802: "-75.12";
837: "-77.76";
803: "-84.75";
808: "-115";
804: "-102.12";
813: "-115";
805: "-115";
801: "-67.53";
836: "-70.36";
}
After the execution of the above code, the contents on sortedKeyWithValues
becomes:
(
806,
803,
837,
802,
836,
801,
808,
813,
805,
804,
)
Notice that the key with the highest value lies at 5th
index of sortedKeyWithValues
. And the key for 2nd
highest value is on the 4th
index and so on. It continues until the first index. The key with the value next to the first index lies at the last index of sortedKeyWithValues
it goes up to the 6th index.
The order of the objects at sortedKeyWithValues
that I'm expecting is:
(
801,
836,
802,
837,
803,
806,
804,
805,
813,
808,
)
What could be the cause for this strange outcome while using sortedArrayUsingComparator
? Is it due to a bug with the method or some silly mistake from my side?
Thank you!
Upvotes: 0
Views: 248
Reputation: 285190
It's not a bug. You are comparing strings not numbers.
NS(Mutable)Dictionary
has a dedicated method keysSortedByValueUsingSelector
to sort keys by values and the selector localizedStandardCompare
sorts strings numerically. The comparator
API is not needed.
NSArray *sortedKeysWithValues = [myDict keysSortedByValueUsingSelector:@selector(localizedStandardCompare:)];
Alternatively use a comparator with option NSNumericSearch
id numericSort = ^(NSString * key1, NSString * key2) {
return [key1 compare:key2 options: NSNumericSearch];
};
NSArray *sortedKeysWithValues = [dictionary keysSortedByValueUsingComparator:numericSort];
Upvotes: 1
Reputation: 7669
Try doing this:
NSArray *myArray;
myArray = [myDict keysSortedByValueUsingComparator: ^(id obj1, id obj2) {
if ([obj1 doubleValue] > [obj2 doubleValue]) {
return (NSComparisonResult)NSOrderedDescending;
}
if ([obj1 doubleValue] < [obj2 doubleValue]) {
return (NSComparisonResult)NSOrderedAscending;
}
return (NSComparisonResult)NSOrderedSame;
}];
Upvotes: 1
Reputation: 1559
That is happening because the values of the NSDictionary
are NSStrings
. compare:
is doing an alphabetical sort.
Quick and dirty fix based on your code:
NSArray *sortedKeysWithValues = [[dic allKeys] sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
return [@([dic[obj2] doubleValue]) compare:@([dic[obj1] doubleValue])];}];
Upvotes: 1
Reputation: 11656
only a couple of notes:
1) what is myDict inside comparison call back?
2) in callback you usually have to get values inside obj1 / obj2 AND compare data members inside them: (eventually casting them... ) for example:
NSArray *sortedPeople = [self.persons sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2){
Person *p1 = (Person *)obj1;
Person *p2 = (Person *)obj2;
return [p1.surname compare:p2.surname];
}];
so I need to know why you use MyDict.
Upvotes: 1