2012-03-03 16 views
0

NSArrayからグループ化されたキーで構造化NSDictionaryを作成する必要があります。
これは一例です:NSArrayから構造化NSDictionaryを作成する

[ 
    { 
     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 
    } 
] 

結果は(私は値がOKであることを確認していなかった、私はアイデアを与えたい)、このような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またはKey-Valueコーディングを使用してこれを達成できますか?多くのループは避けてください。

私の提案された解決策

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

あなたが望むものを達成することができます唯一の方法は、(各レベル:セクション、カテゴリ、日付)ループのネストされた一連のようです。あなたはこのような複雑な述語を作成する最も内側のループでは:

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

その後、入力配列をフィルタリングし、key1のみkey2で辞書の新しい配列を構築します。指定した日付のカテゴリ辞書にこの日付配列を追加してから、特定のカテゴリの出力辞書にカテゴリ辞書を追加します。私はこれを行う簡単な方法はありません。

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

私が作成したばかりのソリューションを追加しました。あなたが良い方がいたら私に知らせてください。 – pasine

+0

一般的な考え方は同じで、何も革命的なものではありませんが、私の答えは更新されました。私は配列を1回だけフィルタリングしていますが、実装よりも速くなるかどうかはわかりません。 – ayoy

関連する問題