【问题标题】:Create a structured NSDictionary from a NSArray从 NSArray 创建结构化 NSDictionary
【发布时间】:2013-02-27 19:54:27
【问题描述】:

我需要创建一个带有分组键的结构化 NSDictionary,从 NSArray 开始。
这是一个例子:

[
    {
        section = section1,
        category = category1,
        date = 2011-12-01,
        key1 = foo,
        key2 = bar
    },
    {
        section = section1,
        category = category2,
        date = 2011-12-01,
        key1 = foo,
        key2 = bar
    },
    {
        section = section1,
        category = category2,
        date = 2011-12-03
        key1 = foo,
        key2 = bar
    },
    {
        section = section2,
        category = category1,
        date = 2011-12-03
        key1 = foo,
        key2 = bar
    }
]  

结果应该是这样的NSDictionary(我没有检查值是否正常,我只是想给出想法):

[
    section1 = {
        category1 = {
            2011-12-01 = 
                [{
                    key1 = foo;
                    key2 = bar;
                },
                {
                    key1 = foo;
                    key2 = bar;
                }
                ]
            }
        },
        category2 = {
            2011-12-01 =
                [{
                    key1 = foo;
                    key2 = bar;
                }],
        }
    },
    section2 = {
        category1 = {
            2011-12-01 =
                [{
                    key1 = foo;
                    key2 = bar;
                }]
        }
    }
]

我可以使用NSPredicate 或键值编码来实现这一点,并避免很多循环吗?

我提出的解决方案

NSMutableDictionary *sectionEmpty = [NSMutableDictionary dictionary];
NSArray *values = [records allValues];

NSArray *sections = [[records allValues] valueForKeyPath:@"@distinctUnionOfObjects.section"];

for(NSString *section in sections) {
    // Find records for section
    NSArray *sectionRecords = [values filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"section == %@",section]];

    // Find unique categories
    NSArray *categorys = [sectionRecords valueForKeyPath:@"@distinctUnionOfObjects.category"];

    // Loop through categories
    for (NSString *category in categorys) {

        // Creating temporary record
        NSMutableDictionary *empty = [NSMutableDictionary dictionary];

        // Find records for category
        NSArray *categoryRecords = [sectionRecords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"category == %@",category]];

        // Find unique dates
        NSArray *dates = [categoryRecords valueForKeyPath:@"@distinctUnionOfObjects.date"];

        // Loop through dates
        for (NSString *date in dates) {

            // Creating temporary record
            NSMutableDictionary *emptyDate = [NSMutableDictionary dictionary];

            // Find records for dates
            NSArray *dateRecords = [categoryRecords filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"date == %@",date]];

            // Split date
            NSString *dateString = [[date componentsSeparatedByString:@" "] objectAtIndex:0];

            // Check if date exist in temporary record
            if(![[emptyDate allKeys] containsObject:dateString]){
                [emptyDate setObject:[NSMutableArray array] forKey:dateString];
            }

            // Set date records for date key
            [[emptyDate objectForKey:dateString] addObject:dateRecords];

            // Set date for category
            [empty setObject:emptyDate forKey:category];
        }

        // Set category for section
        [sectionEmpty setObject:empty forKey:section];
    }

}

【问题讨论】:

    标签: ios loops nsarray nsdictionary key-value


    【解决方案1】:

    似乎您可以实现所需的唯一方法是一系列嵌套的 for 循环(对于每个级别:部分、类别、日期)。在最里面的循环中,您创建一个复杂的谓词,如下所示:

    NSPredicate *predicate = [NSPredicate predicateWithFormat:
                              @"section = %@ AND category = %@ AND date = %@",
                              section, category, date];
    

    然后过滤掉输入数组,并仅使用key1key2 构造新的字典数组。您将此日期数组添加到给定日期的类别字典中,然后将类别字典添加到给定类别的输出字典中。我没有看到任何更简单的方法。

    NSArray *input = [records allValues];
    NSMutableDictionary *output = [NSMutableDictionary dictionary];
    
    
    NSArray *sections = [NSArray valueForKeyPath:@"@distinctUnionOfObjects.section"];
    NSArray *categories = [NSArray valueForKeyPath:@"@distinctUnionOfObjects.category"];
    NSArray *dates = [NSArray valueForKeyPath:@"@distinctUnionOfObjects.date"];
    
    NSPredicate *predicate;
    for (NSString *section in sections) {
        NSMutableDictionary *categoriesDictionary = [NSMutableDictionary dictionary];
    
        for (NSString *category in categories) {
            NSMutableArray *datesArray = [NSMutableArray array];
    
            for (NSString *date in dates) {
                predicate = [NSPredicate predicateWithFormat:
                             @"section = %@ AND category = %@ AND date = %@",
                             section, category, date];
    
                NSArray *filteredInput = [input filteredArrayUsingPredicate:predicate];
                if (filteredInput.count > 0) {
                    NSMutableArray *filteredOutput = [NSMutableArray arrayWithCapacity:filteredInput.count];
    
                    [filteredInput enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
                        [filteredOutput addObject:
                         [NSDictionary dictionaryWithObjectsAndKeys:
                          [obj objectForKey:@"key1"], @"key1",
                          [obj objectForKey:@"key2"], @"key2", nil]
                         ];
                    }];
    
                    if (filteredOutput.count > 0)
                        [datesArray addObject:filteredOutput];
                }
            }
            if (datesArray.count > 0)
                [categoriesDictionary setObject:datesArray forKey:category];
        }
        if (categoriesDictionary.count > 0)
            [output setObject:categoriesDictionary forKey:section];
    }
    

    【讨论】:

    • 我已经添加了我刚刚创建的解决方案。如果你有更好的,请告诉我。
    • 我更新了我的答案,但总体思路是一样的,没有什么革命性的。我只过滤了一次数组,但我不确定它是否会比你的实现更快。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多