2014-05-14 2 views
0

나는 분류 된 식료품 항목의 목록이 tableView 인 프로젝트가 필요합니다. 각 카테고리는 n 깊이를 가질 수 있습니다. API의 JSON 응답은 다음과 같습니다.JSON을 트리 구조로 구문 분석

"items":[ 
{ 
    "id":"5366f8d3e4b0e44dc2d4a6fb", 
    "name":"String Cheese" 
    "description":"Sargento String Cheese", 
    "categorization":[ 
    [ 
     "Dairy", 
     "Cheese" 
    ] 
    ] 
}, 
{ 
    "id":"5366f8d3e4b0e44dc2d1a6fb", 
    "name":"Budlight 6-pk" 
    "description":"Budlight 12-pk", 
    "categorization":[ 
    [ 
     "Beverages", 
     "Alcohol", 
     "Beer" 
    ] 
    ] 
} 
] 

지금은 항목 사전에서 Item 개체를 만들고 아래의 변경 가능한 배열에 저장하고 있습니다.

NSArray *itemsArray = [response objectForKey:items]; 

NSMutableArray *itemsMutableArray = [[NSMutableArray alloc] init]; 
for(NSDictionary *itemDict in itemsArray){ 
    Item *itemObj = [[Item alloc] initWithDictionary:itemDict] 
    [itemsMutableArray addObject:itemObj]; 
} 

나는 itemsMutableArray을 순환에 좋아하고 각 항목에 루트에서 경로를 가지고있는 트리 데이터 구조를 만드는 것입니다. 그런 다음 각 수준의 범주에서 tableViews에 대한 데이터 소스로 트리를 사용할 수 있기를 원합니다.

다음은 내 Item 클래스 헤더의 모양입니다.

@interface Item : NSObject 

@property (nonatomic, strong) NSString *id; 
@property (nonatomic, strong) NSString *name; 
@property (nonatomic, strong) NSString *description; 
@property (nonatomic, strong) NSArray *categorization; 

@end 

... 그리고 구현 내가 트리 데이터 구조와 재귀에 익숙하지 않다

#import "Item.h" 

@implementation Item 

- (id)initWithDictionary:(NSDictionary *)objDictionary{ 
    if (self = [super init]) { 
     self.id = [objDictionary valueForKey:@"id"]; 
     self.name = [objDictionary valueForKey:@"name"]; 
     self.description = [objDictionary valueForKey:@"description"]; 
     self.categorization = [objDictionary valueForKey:@"categorization"]; 
    } 
    return self; 
} 

@end 

. 이 접근법에 대한 도움을 주시면 감사하겠습니다. 감사!

+0

"루트에서 각 항목까지의 경로가있는 트리 데이터 구조를 만듭니다." 무슨 뜻이야? 무엇을 표시 하시겠습니까 ?? – meda

+0

파싱 된 JSON (NSJSONSerialization에서 나온)은 이미 NSDictionary 객체의 NSArray 인 "트리 데이터 구조"입니다. NSDictionary 객체를 똑같은 데이터를 포함하는 사용자 정의 Item 객체로 대체하는 것뿐입니다. 왜?(그리고 재귀에 대한 필요성은 어디서 알 수 있습니까?) –

+0

(위의 루프는'[itemArray addObject : itemObj];'라고 쓰여진 itemsMutableArray를 사용하려는 것입니다.) –

답변

0

간단한 노드 트리 데이터 구조가 필요한 경우. 이 방법은 어때? 희망이 작은 도움이됩니다.

헤더

@interface ItemCategory : NSObject 

@property (nonatomic, strong) NSString *name; 
@property (nonatomic) ItemCategory *parent; 
@property (nonatomic, strong) NSMutableArray *children; 

-(id)initWithName:(NSString *)n parent:(ItemCategory *)p; 
@end 

@interface CategoryTree : NSObject 

@property (nonatomic, strong) ItemCategory *root; 

-(ItemCategory *)_getChildCategory:(ItemCategory *)category name:(NSString *)name; 
-(ItemCategory *)_addChildCategory:(ItemCategory *)category name:(NSString *)name; 
-(void)_dumpCategory:(ItemCategory *)category depth:(int)depth; 

-(void)dump; 
-(ItemCategory *)getCategory:(NSArray *)arr; 
-(void)addCategory:(NSArray *)arr; 

@end 

소스

@implementation CategoryTree 
@synthesize root; 

-(id)init { 
    if (self = [super init]) { 
     root = [[ItemCategory alloc] initWithName:@"root" parent:nil]; 
    } 
    return self; 
} 

-(ItemCategory *)_getChildCategory:(ItemCategory *)category name:(NSString *)name { 
    for (ItemCategory *child in category.children) 
     if ([child.name isEqualToString:name]) 
      return child; 

    return nil; 
} 

-(ItemCategory *)_addChildCategory:(ItemCategory *)category name:(NSString *)name { 
    ItemCategory *child = [self _getChildCategory:category name:name]; 
    if (child) 
     return child; 
    child = [[ItemCategory alloc] initWithName:name parent:category]; 
    [category.children addObject:child]; 

    return child; 
} 

-(void)_dumpCategory:(ItemCategory *)category depth:(int)depth{ 
    NSString *parentStr = @""; 
    ItemCategory *parent = category.parent; 
    while (parent) { 
     parentStr = [NSString stringWithFormat:@"%@%@%@", parent.name, parentStr.length > 0 ? @">" : @"", parentStr]; 
     parent = parent.parent; 
    } 
    NSLog(@"%@%@%@", parentStr, parentStr.length > 0 ? @">" : @"", category.name); 

    for (ItemCategory *child in category.children) { 

     [self _dumpCategory:child depth:depth + 1]; 
    } 
} 

-(void)dump { 
    [self _dumpCategory:root depth:0]; 
} 

-(ItemCategory *)getCategory:(NSArray *)arr { 
    ItemCategory *category = root; 
    for (NSString *categoryName in arr) { 
     category = [self _getChildCategory:category name:categoryName]; 
     if (!category) 
      return nil; 
    } 
    return category; 
} 

-(void)addCategory:(NSArray *)arr { 
    if ([self getCategory:arr]) 
     return; 

    ItemCategory *category = root; 
    for (NSString *categoryName in arr) { 
     ItemCategory *childCategory = [self _getChildCategory:category name:categoryName]; 
     if (!childCategory) { 
      childCategory = [self _addChildCategory:category name:categoryName]; 
     } 
     category = childCategory; 
    } 
} 
@end 

사용

CategoryTree *tree = [[CategoryTree alloc] init]; 
[tree addCategory:@[@"Dairy", @"Cheese"]]; 
[tree addCategory:@[@"Dairy", @"Milk"]]; 
[tree addCategory:@[@"Beverages", @"Alcohol", @"Beer"]]; 
[tree addCategory:@[@"Beverages", @"Alcohol", @"Wine"]]; 
[tree addCategory:@[@"Beverages", @"Non-Alcohol", @"Cola"]]; 
[tree dump]; 

결과

root 
root>Dairy 
root>Dairy>Cheese 
root>Dairy>Milk 
root>Beverages 
root>Beverages>Alcohol 
root>Beverages>Alcohol>Beer 
root>Beverages>Alcohol>Wine 
root>Beverages>Non-Alcohol 
root>Beverages>Non-Alcohol>Cola 
+0

여기서 ItemCategory의 구현입니다. – jimwan

0

잘 당신이 필요로하는 것을 구현하는 방법을 찾았습니다. 나는 얼마나 많은 아이템을 얻지 못할 것이므로 그것이 얼마나 최적화되어 있는지 모른다. 구현 방법은 다음과 같습니다.

는이 트리

[itemsMutableArray enumerateObjectsUsingBlock:^(Item *itm, NSUInteger i,BOOL *stop){ 
     itm.catTree = [NSMutableDictionary dictionary]; 
     NSString *dairy = @"",*beverage = @""; 
     for (NSArray *catArray in itm.categorization) { 
      /* 
       Everything below is written assuming the format of the JSON will be "as-is" 
      */ 

      if ([catArray containsObject:@"Dairy"]) { 
       //Take everything except Dairy 
       NSArray *stripedArray = [catArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != \"Dairy\""]]; 
       int i = 0; 
       //Loop through the array to get any sub categories. 
       while (i < stripedArray.count) { 
        dairy = [dairy stringByAppendingString:[NSString stringWithFormat:(i == stripedArray.count-1)[email protected]"%@ ":@"%@->",stripedArray[i]]]; //Space at the end to account for similar entry in the same category for e.g two dairy products. 
        i++; 
       } 
      } else if ([catArray containsObject:@"Beverages"]) { 
       NSArray *stripedArray = [catArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"SELF != \"Beverages\""]]; 
       int i = 0; 
       while (i < stripedArray.count) { 
        beverage = [beverage stringByAppendingString:[NSString stringWithFormat:(i == stripedArray.count-1)[email protected]"%@ ":@"%@->",stripedArray[i]]]; 
        i++; 
       } 
      } 
     } 


     //Set the category tree for every item using a dictionary 
     [itm.catTree setValue:dairy forKey:@"Dairy"]; 
     [itm.catTree setValue:beverage forKey:@"Beverage"]; 

     NSLog(@"%@",itm.catTree); 
    }]; 

위의 코드에 대한 JSON

{ 
    Beverage = ""; 
    Dairy = "Cheese "; 
} 
{ 
    Beverage = "Alcohol->Beer "; 
    Dairy = ""; 
} 

에 대한 다음과 같은 출력을 제공을 얻을 않는 Item.h @property (nonatomic, strong) NSMutableDictionary *catTree;

다음이 사전을 추가로 시작할 필요 여러 음료

{ 
    Beverage = "Alcohol->Beer Alcohol->Wine->Red Soda->Coke "; 
    Dairy = ""; 
} 

희망이 도움이됩니다.