从NSArray创建结构化NSDictionary

时间:2012-03-03 13:05:00

标签: ios loops nsarray nsdictionary key-value

我需要创建一个带有分组键的结构化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];
    }

}

1 个答案:

答案 0 :(得分:1)

似乎你可以实现你想要的唯一方法是一系列嵌套的for循环(对于每个级别:section,category,date)。在最里面的循环中,您可以创建一个复杂的谓词:

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