开发者

merging an nsarray into an nsset and avoiding duplicates in objective-c on iphone

Edit: better example...

So I have an NSMutableSet of "existing" objects and I'd like to download JSON data, parse it, and merge these new objects with my existing ones, updating any duplicates with the newly downloaded ones. Here's what the existing set of objects looks like:


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", @"999开发者_Go百科9", @"score", nil],
    [NSDictionary dictionaryWithObjectsAndKeys:@"4", @"id", @"what's new", @"body", @"22", @"score", nil],
    nil
];

So for example, after merging this new object, the object with id 1 would now have a score of 9999 and a new object with id 4 would be added to the set.

I really want to avoid looping through the NSMutableSet for every new object just to check that the @"id" property exists... I was thinking I could use addObjectsFromArray to merge these new objects but it looks like since the properties differ (eg: score: 9999) it's not seeing the new objects as an existing object in the set.

I'm using the numbers as strings to simplify this example. I'd also like to avoid using iOS SDK 4.0-only features since the app will be 3.0-compatible.

Thanks a ton! I appreciate it!


Not entirely sure from your question (since its an iphone question, objective c notation should have been used), but it sounds like an NSDictionary could be your best friend.


Your best bet is to convert the first set into a dictionary using the @"id" parameter. Here's some code that should do what you want, and it will even handle the case of having dictionaries that have no @"id" parameter (at which point they won't be merged, just included in the result):

// 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;


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

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜