首先按值排序NSDictionary,然后按键

时间:2016-11-17 22:50:54

标签: objective-c sorting dictionary

所以我有一个类似于此的NSNumber字典(已经按顺序添加了键):

1 : @2000,
2 : @2000,
4 : @1000,
5 : @1000,
6 : @3000

我希望值和键都按升序排序,值的顺序具有更高的优先级。 (由于字典没有像@rmaddy所提到的那样排序,因此得到的有序键和值在单独的数组中)。 结果应该是:

4 : 1000,
5 : 1000,
1 : 2000,
2 : 2000,
6 : 3000

我已经可以使用

获取按值排序的键
NSArray<NSNumber *> *sortedKeys = [dict keysSortedByValueUsingSelector:@selector(compare:)];

但这当然不尊重键的顺序。

免责声明:Swift中已解决此问题的解决方案here但我无法弄清楚如何在Obj-C中实现

2 个答案:

答案 0 :(得分:1)

好的,您需要两个单独的数组,其中一个是字典的排序值,另一个是排序以与值对应的键。此外,与相同值关联的两个键应按两个键的自然顺序排序。

对值进行排序很容易。但是没有任何内置功能可以按照您想要的方式对相应的键进行排序。问题是获取按键顺序排序的相等值的键。下面的代码是一个可以产生预期结果的解决方案。

NSDictionary *dict = @{@1 : @2000,
                      @2 : @2000,
                      @4 : @1000,
                      @5 : @1000,
                       @6 : @3000};

NSArray *sortedValues = [dict.allValues sortedArrayUsingSelector:@selector(compare:)];
NSOrderedSet *uniqueValues = [NSOrderedSet orderedSetWithArray:sortedValues];
NSMutableArray *sortedKeys = [NSMutableArray arrayWithCapacity:dict.count];
for (id val in uniqueValues) {
    NSArray *keys = [dict allKeysForObject:val];
    [sortedKeys addObjectsFromArray:[keys sortedArrayUsingSelector:@selector(compare:)]];
}

NSLog(@"dict: %@", dict);
NSLog(@"keys: %@, values: %@", sortedKeys, sortedValues);

输出:

dict: {
    6 = 3000;
    2 = 2000;
    5 = 1000;
    1 = 2000;
    4 = 1000;
}
keys: (
    4,
    5,
    1,
    2,
    6
), values: (
    1000,
    1000,
    2000,
    2000,
    3000
)

答案 1 :(得分:1)

我从一个可排序的数据结构开始:

NSDictionary *d = @{@1 : @2000,
                    @2 : @2000,
                    @4 : @1000,
                    @5 : @1000,
                    @6 : @3000};

NSMutableArray *array = [[NSMutableArray alloc] init];
for (id key in [d allKeys]) {
    [array addObject:@[key, d[key]]];
}

这会给我们:

@[ @[@6, @3000], @[@2, @2000], ...]

现在,我们可以编写一个比较器来比较你喜欢的。我从OP中理解的是,我们希望对键进行主要排序,并对键进行次要(打破平局)排序:

[array sortUsingComparator:^NSComparisonResult(id elementA, id elementB) {
    NSNumber *valueA = ((NSArray *)elementA)[1];
    NSNumber *valueB = ((NSArray *)elementB)[1];
    if ([valueA isEqualToNumber:valueB]) {
        NSNumber *keyA = ((NSArray *)elementA)[0];
        NSNumber *keyB = ((NSArray *)elementB)[0];
        return [keyA compare:keyB];
    } else {
        return [valueA compare:valueB];
    }
}];

NSLog(@"%@", array);