Can I Use NSPredicate with NSSet

4.1k views Asked by At

i want to get intersect of two NSSet, by default NSSset compare every member of object for concluding intersection objects in SetA and SetB.

here is my code.

NSMutableDictionary *dic = [[NSMutableDictionary alloc]init];
[dic setObject:@"25" forKey:@"age"];
[dic setObject:@"abc" forKey:@"Name"];

NSMutableDictionary *dic1 = [[NSMutableDictionary alloc]init];
[dic1 setObject:@"21" forKey:@"age"];
[dic1 setObject:@"xyz" forKey:@"Name"];

NSMutableDictionary *dic2 = [[NSMutableDictionary alloc]init];
[dic2 setObject:@"20" forKey:@"age"];
[dic2 setObject:@"abc" forKey:@"Name"];

NSMutableDictionary *dic3 = [[NSMutableDictionary alloc]init];
[dic3 setObject:@"25" forKey:@"age"];
[dic3 setObject:@"abcNameNotMatch" forKey:@"Name"];

NSMutableDictionary *dic4 = [[NSMutableDictionary alloc]init];
[dic3 setObject:@"20" forKey:@"age"];
[dic3 setObject:@"abcNameNotMatch" forKey:@"Name"];

NSArray *a = [NSArray arrayWithObjects:dic,dic1,dic2, nil];
NSArray *b = [NSArray arrayWithObjects:dic3,dic4, nil];

NSMutableSet *setA = [NSMutableSet setWithArray:a];
NSSet *setB = [NSSet setWithArray:b];
//[setA intersectSet:setB];
//NSLog(@"c: %@", [setA allObjects]);

[setA intersectSet:setB];

NSLog(@"d: %@", [setA allObjects]); 

I want to get filter object(intersect) only on the basis of age. in Short, can i specify that intersectSet function should compare only age of SetA and SetB.MeanWhile, ignore values of name. 2 object should be return dic and dic2 by using my code. intersecting objects in setA and setB is. for help.

setA

1)dic age is 25

2)dic2 age is 20

setB

1)dic3 age is 25

2)dic4 age is 20

2

There are 2 answers

6
rintaro On BEST ANSWER

Try:

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age in %@.age", setB];
NSSet *result =  [setA filteredSetUsingPredicate:predicate];

If you want to modify setA itself, use:

[setA filterUsingPredicate:predicate];

example:

NSMutableSet *setA = [NSMutableSet setWithArray:
                      @[
                        @{@"age":@(11), @"Name":@"abc"},
                        @{@"age":@(11), @"Name":@"def"},
                        @{@"age":@(22), @"Name":@"ghi"},
                        @{@"age":@(22), @"Name":@"jkl"},
                        @{@"age":@(33), @"Name":@"lmn"},
                        @{@"age":@(33), @"Name":@"opq"},
                        ]];
NSSet *setB = [NSSet setWithArray:
               @[
                 @{@"age":@(11), @"Name":@"rst"},
                 @{@"age":@(22), @"Name":@"uvw"},
                 @{@"age":@(22), @"Name":@"xyz"},
                 ]];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"age in %@.age", setB];
[setA filterUsingPredicate:predicate];
NSLog(@"%@", setA);

output:

{(
        {
        Name = abc;
        age = 11;
    },
        {
        Name = def;
        age = 11;
    },
        {
        Name = ghi;
        age = 22;
    },
        {
        Name = jkl;
        age = 22;
    }
)}
0
fguchelaar On

You could write a specific 'wrapper'-class for this problem and override the isEqual: and hash: methods.

Have it check for equality using the dictionaries age key. Put the wrappers in sets and intersect.