0

I have two arrays of key-value pairs. Both these arrays contain different key-value pairs. I want to find elements in the first array that are not part of the second array based on a particular key.

Example:

1st Array - [{id=1, name="foo"}, {id=2, name="bar"}]

2nd Array - [{id=2, name="abc"}, {id=1, name="xyz"}]

Is there a way I can implement the same? Right now I enumerate through the two arrays like so:

for (NSDictionary *eachPlayer in 1stArray) {
        for (NSDictionary *eachPrediction in 2ndArray) {
            if (eachPrediction[kId] != eachPlayer[kId]) {
                [self.predictPlayerArray addObject:eachPlayer];
            }
        }
    }

But this fails in the above case and adds both the values to the predictionPlayerArray - in the first iteration it adds 1 and in the forth iteration it adds 2. How do I prevent that from happening? Thanks.

EDIT

I seem to have solved it this way. Not the best solution but it seems to be working:

for (NSDictionary *eachPlayer in arrayOne) {
        for (NSDictionary *eachPrediction in arrayTwo) {
            if (eachPrediction[kId] == eachPlayer[kId]) {
                if ([self.predictPlayerArray containsObject:eachPlayer]) {
                    [self.predictPlayerArray removeObject:eachPlayer];
                }
                break;
            }
            else {
                [self.predictPlayerArray addObject:eachPlayer];
            }
            self.predictPlayerArray = [self.predictPlayerArray valueForKeyPath:@"@distinctUnionOfObjects.self"];
        }
    }
Anil
  • 2,430
  • 3
  • 37
  • 55
  • 1
    can you tell us what you want to accomplish in the resulting array? the values are different for each array. if you want to check for the key to be present the approach is slightly different – Pablo Carrillo Alvarez Feb 03 '15 at 13:35
  • In this case the resulting array should be nil. Now if the first array had one more entry say [3 :"abc"], resulting will be [3 :"abc"] – Anil Feb 03 '15 at 13:38
  • 1
    A `NSPredicate` and maybe looking for `@unionOfArarys` or maybe NOT IN (http://stackoverflow.com/questions/8580715/nsarray-with-nspredicate-using-not-in), since it's unclear what you really want. – Larme Feb 03 '15 at 13:57
  • @Anil You said "I want to find elements in the first array that are not part of the second array based on a particular key," but want the resulting array to be nil even though none of the elements in the 1st array are part of the 2nd... I agree that it's unclear what you want... – Lyndsey Scott Feb 03 '15 at 14:04
  • @LyndseyScott I've made an edit to the example. – Anil Feb 03 '15 at 14:26

1 Answers1

0

Something like this should do:

NSArray *array1 = @[@{@"1":@"foo"},@{@"2":@"bar"},@{@"3":@"abc"}];
NSArray *array2 = @[@{@"2":@"abc"},@{@"1":@"abc"},@{@"4":@"foo"}];
NSMutableSet *result = [NSMutableSet new];
for (NSDictionary *dict1 in array1){
    [dict1 enumerateKeysAndObjectsUsingBlock:^(id key1, id obj1, BOOL *stop1) {
        for (NSDictionary *dict2 in array2) {
            [dict2 enumerateKeysAndObjectsUsingBlock:^(id key2, id obj2, BOOL *stop2) {
                if ([obj2 isEqual:obj1]){
                    [result addObject:@{key1:obj1}];
                    *stop2 = YES;
                }
            }];
        }
    }];
}
NSLog(@"result %@", result);

As you has nested dictionaries you should iterate also in them and finally store the result in a set that would prevent to have duplicate entries (if you use a NSMutableArray you will have twice {3:abc})

The log output is:

2015-02-03 13:53:07.897 test[19425:407184] result {(
    {
    1 = foo;
},
    {
    3 = abc;
}
)}