将NSDictionary排序为NSMutableArray但保留值和密钥?

时间:2012-11-30 10:19:59

标签: objective-c sorting nsarray nsdictionary

我有点困惑:尝试列出我在NSDictionary中的玩家姓名和分数列表,并将它们分类为分数顺序(最高分排名第一)。我知道我不能对字典进行排序所以我需要先将数据移动到一个数组中,但这样做,我不会丢失每个字典键/值对的一半吗?

例如,假设我有以下几对:

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

如果我拿出分数并对它们进行排序,然后在以后检索密钥,John和Stan会不会因为分数相同而混淆了?可能会把它们中的一个叫两次,等等?

我意识到我无法对字典进行排序,但有更聪明的方法吗?

2 个答案:

答案 0 :(得分:4)

你可以做的是根据他们的得分获得一个排序的玩家阵列,然后为每个玩家创建一个字典并将它们附加到另一个阵列中。也许是这样的事情(我使用新的文字语法,如果合适的话,使用旧的语法):

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

现在您的players数组是:

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

PS。保留一个字典,其中键是玩家名称不是一个好主意,考虑到你有两个不同的John玩家......那么会发生什么?另外一个更好的解决方案是创建一个Player类并将其数据(分数,名称等)保存为属性。

答案 1 :(得分:0)

你必须创建两个阵列,一个用于得分,另一个用于玩家。关键点在于玩家阵列与(排序)得分数组的顺序相同。下面的实现假定您使用NSNumber对象保留分数,并且因为它对值进行两次排序而不是特别有效:

(未测试的)

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