将nsarray合并到nsset中,避免在iphone上的objective-c中重复

时间:2010-10-28 18:22:19

标签: iphone objective-c nsarray nsdictionary nsset

编辑:更好的例子......

所以我有一个“现有”对象的NSMutableSet,我想下载JSON数据,解析它,并将这些新对象与现有对象合并,用新下载的对象更新任何重复项。这是现有的一组对象的样子:


NSArray *savedObjects = [NSArray arrayWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"200", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"2", @"id", @"hey now", @"body", @"10", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"3", @"id", @"welcome!", @"body", @"123", @"score", nil],
    nil
];
self.objects = [NSMutableSet setWithArray:savedObjects];

// after downloading and parsing JSON... I have an example array of objects like this:

NSArray *newObjects = [NSArray arrayWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"9999", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"4", @"id", @"what's new", @"body", @"22", @"score", nil],
    nil
];

例如,在合并这个新对象之后,id为1的对象现在的分数为9999,而id为4的新对象将被添加到该集合中。

我真的想避免为每个新对象循环遍历NSMutableSet只是为了检查@“id”属性是否存在...我以为我可以使用addObjectsFromArray来合并这些新对象,但它看起来像是因为属性不同(例如:得分:9999)它没有将新对象看作集合中的现有对象。

我使用数字作为字符串来简化此示例。我还想避免使用iOS SDK 4.0专用功能,因为该应用程序将与3.0兼容。

非常感谢!我很感激!

3 个答案:

答案 0 :(得分:4)

不完全确定你的问题(因为它的iphone问题,应该使用客观的符号),但听起来像NSDictionary可能是你最好的朋友。

答案 1 :(得分:0)

NSArray *array = ... // contains the new dictionary objects.
NSMutableSet *set = ... // contains the existing set of dictionary objects. 

for (id arrayItem in array)
{
    id setItem = [[set filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"id.intValue = %d", [[arrayItem valueForKey:@"id"] intValue]]] anyObject];
    if (setItem != nil)
    {
        [set removeObject:setItem];
        [set addObject:arrayItem];
    }
}

答案 2 :(得分:0)

最好的办法是使用@“id”参数将第一组转换为字典。这里有一些代码可以做你想要的,它甚至可以处理没有@“id”参数的字典(此时它们不会被合并,只包括在结果中):

// here is the NSSet you already have
self.objects = [NSSet setWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"200", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"2", @"id", @"hey now", @"body", @"10", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"3", @"id", @"welcome!", @"body", @"123", @"score", nil],
    nil];

// after downloading and parsing JSON... I have an example array of objects like this:

NSArray *newObjects = [NSArray arrayWithObjects:
    [NSDictionary dictionaryWithObjectsAndKeys:@"1", @"id", @"hello there", @"body", @"9999", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"4", @"id", @"what's new", @"body", @"22", @"score", nil],
    nil];

// Convert self.objects into a dictionary for merging purposes
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:[self.objects count]];
NSMutableSet *remainder = [NSMutableSet set]; // for objects with no @"id"
for (NSDictionary *obj in self.objects) {
    NSString *objId = [obj objectForKey:@"id"];
    if (objId) {
        [dict setObject:obj forKey:objId];
    } else {
        [remainder addObject:obj];
    }
}

// merge the new objects in
for (NSDictionary *obj in newObjects) {
    NSString *objId = [obj objectForKey:@"id"];
    if (objId) {
        // merge the new dict with the old
        // if you don't want to merge the dict and just replace,
        // simply comment out the next few lines
        NSDictionary *oldObj = [dict objectForKey:objId];
        if (oldObj) {
            NSMutableDictionary *newObj = [NSMutableDictionary dictionaryWithDictionary:oldObj];
            [newObj addEntriesFromDictionary:obj];
            obj = newObj;
        }
        // stop commenting here if you don't want the merging
        [dict setObject:newObj forKey:objId];
    } else {
        [remainder addObject:obj];
    }
}

// add the merged dicts back to the set
[remainder addObjectsFromArray:[dict allValues]];
self.objects = remainder;