建立一对多关系的最佳方式是什么?

时间:2013-04-11 15:18:39

标签: objective-c performance algorithm

我有一组Videos个对象,其中包括属性idtags

我想构建一个字典,其keytag,其valueid的数组。

例如,某些Video对象可能如下所示:

Video{ id:1, tags:[funny,political,humor] }

Video{ id:2, tags:[political,america] }

我希望结果字典看起来像这样:

VideosWithTags["funny":[1]; "political":[1,2]; "humor":[1]; "america":[2]]

是否有标准算法来实现这一目标?

目前我正在做这样的事情:

for (NSDictionary *video in videos)
{
    NSNumber *videoId = [video objectForKey:@"id"];
    NSArray *tags = [video objectForKey:@"tags"];

    for (NSString *tag in tags)
    {
        NSMutableArray *videoIdsForTag = nil;

        if ([videosAndTags objectForKey:tag] != nil) //same tag with videoIds already exists
        {
            videoIdsForTag = [videosAndTags objectForKey:tag];
            [videoIdsForTag addObject:videoId];

            //add the updated array to the tag key
            [videosAndTags setValue:videoIdsForTag forKey:tag];
        }
        else //tag doesn't exist yet, create it and add the videoId to a new array
        {
            NSMutableArray *videoIds = [NSMutableArray array];
            [videoIds addObject:videoId];

            //add the new array to the tag key
            [videosAndTags setObject:videoIds forKey:tag];
        }
    }
}

2 个答案:

答案 0 :(得分:1)

使用新的文字语法可以使这个看起来更清晰。

我认为通过让if分支机构减少工作量,您可以从中受益。例如你最好尝试检索videoIds数组,如果它不存在 - 创建它并将其添加到videosAndTags对象,然后在此点之后的代码可以与没有重复的逻辑

for (NSDictionary *video in videos) {
  NSNumber *videoId = video[@"id"];
  NSArray  *tags    = video[@"tags"];

  for (NSString *tag in tags) {
    NSMutableArray *videoIds = videosAndTags[tag];
    if (!videoIds) {
      videoIds = [NSMutableArray array];
      videosAndTags[tag] = videoIds;
    }

    // This is the only line where I manipulate the array
    [videoIds addObject:videoId]; 
  }
}

答案 1 :(得分:1)

NSArray* videos =
    @[@{ @"id" : @1, @"tags" : @[ @"funny", @"political", @"humor" ] },
      @{ @"id" : @2, @"tags" : @[ @"political", @"america" ] } ];
NSMutableDictionary* videosAndTags = [NSMutableDictionary new];

// find distinct union of tags
NSArray* tags = [videos valueForKeyPath: @"@distinctUnionOfArrays.tags"];

// for each unique tag
for( NSString* tag in tags )
{
    // filter array so we only have ones that have the right tag
    NSPredicate* p = [NSPredicate predicateWithFormat: @"tags contains %@", tag];
    videosAndTags[ tag ] = [[videos filteredArrayUsingPredicate: p] valueForKeyPath: @"id"];
}

这是使用NSPredicate和valueForKeyPath的另一种方法。

我不经常使用它们,但有时它们可​​以被证明是有用的。

(我认为他们称之为功能编程风格的东西,但我不太确定)

NSPredicate reference
Key Value Coding