2
votes

I'm a little confused: trying to take a list of player names and scores that I have in an NSDictionary, and sort them into score order (highest score first). I know I can't sort a Dictionary so I need to move the data into an array first, but in doing so, won't I have to lose one half of each dictionary key/value pair?

For example, let's say I have the following pairs:

Bill / 10000
John / 7500
Stan / 7500
Mark / 5000

If I go and take the scores out and sort them, then retrieve the keys later, won't John and Stan get mixed up since they had identical scores? Might it call one of them twice, etc?

I realise I can't sort the dictionary, but is there a smarter way to do this?

2

2 Answers

4
votes

What you could do is to get a sorted array of your players based on their score, and then create a dictionary for each player and append them in another array. Something like this perhaps (I'm using the new literals syntax, use the old one if appropriate):

NSDictionary *scores = @{
    @"Stan" : @7500,
    @"Mark" : @5000,
    @"John" : @7500,
    @"Bill" : @10000
};

NSArray *sp = [scores keysSortedByValueUsingComparator:^(id obj1, id obj2){
    return [obj2 compare:obj1];
}];

NSMutableArray *players = [NSMutableArray arrayWithCapacity:0];
for (NSString *p in sp) [players addObject:@{ @"name":p, @"score":scores[p] }];

Now your players array is:

(
        {
        name = Bill;
        score = 10000;
    },
        {
        name = John;
        score = 7500;
    },
        {
        name = Stan;
        score = 7500;
    },
        {
        name = Mark;
        score = 5000;
    }
)

PS. Is not a good idea to keep a dictionary where the keys are player names, consider that you got 2 different John players... what would happen then? Also a better solution imo would be to create a Player class and keep their data (score, name etc) as properties.

0
votes

You'll have to create two arrays, one for the score and another for the player. The key point being that the player array is in the same order as the (sorted) score array. The implementation below assumes you keep the score using an NSNumber object, and is not particularly efficient as it sorts the values twice:

(untested)

NSDictionary *dict = ...;    // key=player (NSString), value=score (NSNumber).

NSArray *scores = [[dict allValues] sortedArrayUsingComparator:^(id obj1, id obj2) {
    return [(NSNumber *)obj2 compare:(NSNumber *)obj1];
}];

NSArray *players = [dict keysSortedByValueUsingComparator:^(id obj1, id obj2) {
    return [(NSNumber *)obj2 compare:(NSNumber *)obj1];
}];