【问题标题】:Obj C: Grouping strings into NSMutableDictionaryObj C:将字符串分组到 NSMutableDictionary
【发布时间】:2026-02-10 19:50:01
【问题描述】:

我有一个包含一堆字符串的 NSArray。每个字符串都列出了一个父子类型,如:

Tool: Saw
Fruit: Apple
Fruit: Orange
Tree: Maple
Fruit: Banana
Tree: Oak
Tool: Hammer
Tree: Cedar

我需要将它们放入的最终结构是(排序的父母和孩子):

Fruit:
  - Apple
  - Banana
  - Orange
Tool:
  - Hammer
  - Saw
Tree:
  - Cedar
  - Maple
  - Oak

我想知道如何将它们分组到它们的父类型下,按该父类型排序并对子类型进行排序。我认为最好使用 NSMutableDictionary 将它们变成键和对象。

这是我到目前为止测试的结果,但结果不是我想要的:

// Add to tree
if ([tree objectForKey:pathParent]) {
    NSMutableArray *temp = (NSMutableArray *)[tree objectForKey:pathParent];
    [temp addObject:name];
    [tree removeObjectForKey:pathParent];
    [tree setObject:temp forKey:pathParent];

} else {
    [tree setObject:[NSMutableArray arrayWithObject:name] forKey:pathParent];
}//end

我该怎么做?

【问题讨论】:

  • 是的,您可以使用 NSScanner 或 NSRange 类来获取字符串的不同部分。然后,如果第一部分等于字典中的一个键,则将第二部分作为值放入。
  • 您是否只是在询问是否有可能,或者寻求一些有关如何做到这一点的指导? NSDictionary 的键没有固有的顺序,因此“水果”、“工具”等不会被排序。每个键的对象可以是一个 NSArray(例如 ["Apple","Banana","Orange"]),并且可以将它们排序为一个数组。
  • 我需要指导。
  • 哈,不是作业,我正在举一个非常笼统的例子来说明我需要解决的更复杂的问题。

标签: objective-c ios nsmutablearray nsmutabledictionary


【解决方案1】:

我认为最简单的方法是对原始列表执行字母排序

Tool: Saw
Fruit: Apple
Fruit: Orange
Tree: Maple
Fruit: Banana
Tree: Oak
Tool: Hammer
Tree: Cedar

获取:

Fruit: Apple
Fruit: Banana
Fruit: Orange
Tool: Hammer 
Tool: Saw
Tree: Cedar
Tree: Maple
Tree: Oak

从那里您可以轻松地遍历数组并对其进行格式化。查看第一个字符串的第一部分并打印它,然后换行第二部分。查看第二个字符串,如果它的第一部分不同,您有一个新的父级,所以像第一个一样打印,否则只打印字符串的第二部分。以这种方式继续。

您还可以将元素存储在树中,这样您就可以拥有一个带有子节点的树,而不是“父:节点”格式的字符串列表。这将使您能够拥有具有子节点的子节点等等。

第一个选项有效,但树数据结构是更健壮的选项,更容易扩展。

如果这些没有意义,请告诉我,我会更新以澄清。

【讨论】:

  • 是的,这是有道理的。我想将它存储在树结构中。您是否建议使用键(水果、工具、树)的 NSDictionary,并且每个键的对象都是 NSArray?
  • 我建议你编写自己的树数据结构,有点像二叉树,但每个节点最多有 n 个子节点。在您当前的示例中,您需要一个通用根节点来连接所有“类别”,从而使您的树非常宽,但这不一定是一件坏事。 NSArrays 的 NSDictionary 将适用于给出的示例,但如果您想添加另一个深度级别,这将非常困难。
【解决方案2】:

[NVM,我看到你已经让它工作了!酷。]

大致这样的东西应该可以工作,当然你需要调味和调试才能品尝。但这是一般的想法......

- (NSDictionary*)categoriesAndSortedItemsFromItems:(NSArray*)source {

    //Given NSArray *source with the lines you described...

    NSMutableDictionary *categoriesAndItems = [NSMutableDictionary dictionaryWithCapacity:3];

    // Plug the items into the correct arrays by category
    for (NSString *line in source) {

        NSArray *components = [line componentsSeparatedByString:@": "];
        NSString *category = [components objectAtIndex:0]; //e.g. "tree"
        NSString *item = [components objectAtIndex:1]; //e.g. "oak"

        NSMutableArray *itemsForCategory = [self arrayInDict:categoriesAndItems forKey:category];

        [itemsForCategory addObject:item];
    }

    // Now run through and sort each array if you want...
    NSMutableDictionary *categoriesAndSortedItems = [NSMutableDictionary dictionaryWithCapacity:3];

    [categoriesAndItems enumerateKeysAndObjectsUsingBlock:^(id key, id obj, BOOL *stop) {

        NSArray *sorted = [(NSArray*)obj sortedArrayUsingSelector:@selector(compare:)];
        [categoriesAndSortedItems setObject:sorted forKey:key];
    }];

    return categoriesAndSortedItems;

}

 - (NSMutableArray*)arrayInDict:(NSMutableDictionary*)dict forKey:(NSString*)key {

        NSMutableArray *array = [dict objectForKey:key];

        if (!array)  {

            array = [[NSMutableArray alloc] initWithCapacity:10];

            [dict setObject:array forKey:key];

            [array release];
        }

        return array;
    }

【讨论】:

    【解决方案3】:

    这就是我在 for 循环中所做的工作:

    if (pathParent != nil) {
        if ([tree objectForKey:pathParent]) {
            [[tree objectForKey:pathParent] addObject:name];
        } else {
            [tree setObject:[NSMutableArray arrayWithObject:name] forKey:pathParent];
        }//end
    }//end
    

    【讨论】:

    • 小事一桩,如果数组存在,只要[temp addObject:name]即可。无需从字典中删除该数组,然后再次添加相同的数组。所以你可以省略这两行。