Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Comparing two NSDictionaries and Find Difference

I am working on an iOS app, where I will be getting a JSON Object from server, which will be populated on a UITableView.

User can change values on tableview, Hence resulting in a new JSON. Now I want to send only delta (Difference of Two JSON Objects) back to server. I know I can traverse both Objects for finding delta. But just wish to know is there any easy solution for this problem.

Ex:

NSDictionary *dict1 = {@"Name" : "John", @"Deptt" : @"IT"};
NSDictionary *dict2 = {@"Name" : "Mary", @"Deptt" : @"IT"};

Delta = {@"Name" : "Mary"}

Considering new value is Mary for key name;

Thanks In Advance

like image 723
Yukta Arora Avatar asked Jul 14 '16 13:07

Yukta Arora


3 Answers

isEqualToDictionary: Returns a Boolean value that indicates whether the contents of the receiving dictionary are equal to the contents of another given dictionary.

if ([NSDictionary1 isEqualToDictionary:NSDictionary2) {
   NSLog(@"The two dictionaries are equal.");
}

Two dictionaries have equal contents if they each hold the same number of entries and, for a given key, the corresponding value objects in each dictionary satisfy the isEqual: test.

like image 112
Haroun SMIDA Avatar answered Nov 08 '22 22:11

Haroun SMIDA


Here's how to get all the keys with non-matching values. What to do with those keys is app level question, but the most informative structure would include an array of mismatched values from both dictionaries, as well has handle keys from one that are not present in the other:

NSMutableDictionary *result = [@{} mutableCopy];

// notice that this will neglect keys in dict2 which are not in dict1
for (NSString *key in [dict1 allKeys]) {
    id value1 = dict1[key];
    id value2 = dict2[key];
    if (![value1 equals:value2]) {
        // since the values might be mismatched because value2 is nil
        value2 = (value2)? value2 : [NSNull null];
        result[key] = @[value1, value2];
    }
}

// for keys in dict2 that we didn't check because they're not in dict1
NSMutableSet *set1 = [NSMutableSet setWithArray:[dict1 allKeys]];
NSMutableSet *set2 = [NSMutableSet setWithArray:[dict2 allKeys]];
[set2 minusSet:set1]
for (NSString *key in set2) {
    result[key] = @[[NSNull null], dict2[key]];
}

There are certainly more economical ways to do it, but this code is optimized for instruction.

like image 41
danh Avatar answered Nov 08 '22 20:11

danh


Just enumerate through and compare the dictionaries key-by-key. This will output any differences as well as any unmatched keys on either side, you can tweak the logic depending on exactly what you want to include.

- (NSDictionary *)delta:(NSDictionary *)dictionary
{
    NSMutableDictionary *result = NSMutableDictionary.dictionary;

    // Find objects in self that don't exist or are different in the other dictionary
    [self enumerateKeysAndObjectsUsingBlock:^(id  _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        id otherObj = dictionary[key];

        if (![obj isEqual:otherObj]) {
            result[key] = obj;
        }
    }];

    // Find objects in the other dictionary that don't exist in self
    [dictionary enumerateKeysAndObjectsUsingBlock:^(id _Nonnull key, id  _Nonnull obj, BOOL * _Nonnull stop) {
        id selfObj = self[key];

        if (!selfObj) {
            result[key] = obj;
        }
    }];

    return result;
}
like image 2
trapper Avatar answered Nov 08 '22 21:11

trapper