【问题标题】:Get NSArray of NSDictionary keys sorted by Value then Key获取按值排序的 NSDictionary 键的 NSArray,然后按键
【发布时间】:2012-09-24 18:19:36
【问题描述】:

假设我有一个包含键(单词)和值(分数)的字典,如下所示:

GOD    8
DONG   16
DOG    8
XI     21

我想创建一个字典键(单词)的 NSArray,它首先按分数排序,然后按字母顺序排序。从上面的示例中,这将是:

XI
DONG
DOG
GOD

实现这一目标的最佳方法是什么?

【问题讨论】:

    标签: objective-c cocoa-touch cocoa nsdictionary nssortdescriptor


    【解决方案1】:

    我会使用 NSDictionaries 和 NSArray,然后使用 NSSortDescriptors 实现它:

    NSSortDescriptor *sdScore = [NSSortDescriptor alloc] initWithKey:@"SCORE" ascending:NO];
    NSSortDescriptor *sdName = [NSSortDescriptor alloc] initWithKey:@"NAME" ascending:YES];
    NSArray *sortedArrayOfDic = [unsortedArrayOfDic sortedArrayUsingDescriptors:[NSArray arrayWithObjects: sdScore, sdName, nil]];
    

    【讨论】:

    • 如何从我的原始字典中构造这个字典数组?
    • 好的,想通了。我希望它会简单得多。这将是 C# LINQ 中的单行代码!
    • @DanielSkinner 如果你想要单行,也许你可以根据 Carlos 的解决方案编写一个类别来做你想做的事。
    • 但是如果数值是 2 和 21 会发生什么?然后在排序数组中,编号为 21 的字典后面将跟随编号为 2 的字典
    【解决方案2】:

    Carlos 的回答是正确的,我只是发布了我最终得到的完整代码,以防万一有人感兴趣:

    NSDictionary *dataSourceDict = [NSDictionary dictionaryWithObjectsAndKeys:
                          [NSNumber numberWithInt:8], @"GOD",
                          [NSNumber numberWithInt:16], @"DONG",
                          [NSNumber numberWithInt:8], @"DOG",
                          [NSNumber numberWithInt:21], @"XI", nil];
    
    NSSortDescriptor *scoreSort = [NSSortDescriptor sortDescriptorWithKey:@"SCORE" ascending:NO];
    NSSortDescriptor *wordSort = [NSSortDescriptor sortDescriptorWithKey:@"WORD" ascending:YES];
    NSArray *sorts = [NSArray arrayWithObjects:scoreSort, wordSort, nil];
    
    
    NSMutableArray *unsortedArrayOfDict = [NSMutableArray array];
    
    for (NSString *word in dataSourceDict)
    {
        NSString *score = [dataSourceDict objectForKey:word];
        [unsortedArrayOfDict addObject: [NSDictionary dictionaryWithObjectsAndKeys:word, @"WORD", score, @"SCORE",  nil]];
    }
    NSArray *sortedArrayOfDict = [unsortedArrayOfDict sortedArrayUsingDescriptors:sorts];
    
    NSDictionary *sortedDict = [sortedArrayOfDict valueForKeyPath:@"WORD"];
    
    NSLog(@"%@", sortedDict);
    

    相关:NSDictionary split into two arrays (objects and keys) and then sorted both by the objects array (or a similar solution)

    【讨论】:

    • 有一种更简单的方法可以实现这一点。看看 NSArray 的 allKeys 和 allValues 方法。
    【解决方案3】:

    我无法对此进行测试,因为我不在 Mac 上(对不起,如果我拼错了什么),但是:

    NSDictionary *dic1 = [NSDictionary dictionaryWithObjectsAndKeys:@"GOD", @"WORD", [NSNumber numberWithInt:8], @"SCORE", nil];
    NSDictionary *dic2 = [NSDictionary dictionaryWithObjectsAndKeys:@"DONG", @"WORD", [NSNumber numberWithInt:16], @"SCORE", nil];
    NSDictionary *dic3 = [NSDictionary dictionaryWithObjectsAndKeys:@"DOG", @"WORD", [NSNumber numberWithInt:8], @"SCORE", nil];
    NSDictionary *dic4 = [NSDictionary dictionaryWithObjectsAndKeys:@"XI", @"WORD", [NSNumber numberWithInt:21], @"SCORE", nil];
    
    NSSortDescriptor *scoreSort = [NSSortDescriptor sortDescriptorWithKey:@"SCORE" ascending:NO];
    NSSortDescriptor *wordSort = [NSSortDescriptor sortDescriptorWithKey:@"WORD" ascending:YES];
    
    NSArray *sortedArrayOfDic = [[NSArray arrayWithObjects:dic1, dic2, dic3, dic4, nil] sortedArrayUsingDescriptors:[NSArray arrayWithObjects:scoreSort, wordSort, nil]];
    
    NSLog(@"%@", [sortedArrayOfDict valueForKeyPath:@"WORD"]);
    

    这会做同样的事情,但会有所减少并避免迭代。

    【讨论】:

    • 好的,但是如果我只是给了一个未知大小和内容的 NSDictionary,我就必须像我一样进行迭代,对吗?或者我还能简化事情吗?
    • 我认为您必须进行迭代。但是让我说,如果你将所有数据放在一个带有键(单词)和值(分数)对的 NSDictionary 中,你就会失去字典数据结构的本质。这被认为与字段标识符和字段值对一起使用。标识符必须沿字典保持不变,以便您可以使用 objectForKey 直接访问它。将其视为类似于 Java 中的 HashMap(如果您了解 Java)。您以这种方式使用的只是两个简单的数组,一个是键,另一个是值,它们之间仅通过字典中的索引链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-03
    • 2014-04-07
    • 1970-01-01
    • 2015-08-25
    相关资源
    最近更新 更多