Using NSPredicate to filter based on multiple keys (NOT values for key)

浪尽此生 提交于 2019-11-27 00:58:14

问题


I have the following NSArray containing NSDictionary(s):

NSArray *data = [[NSArray alloc] initWithObjects:
                 [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:1], @"bill", [NSNumber numberWithInt:2], @"joe", nil],
                 [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:3], @"bill", [NSNumber numberWithInt:4], @"joe", [NSNumber numberWithInt:5], @"jenny", nil],
                 [NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithInt:6], @"joe", [NSNumber numberWithInt:1], @"jenny", nil],
                 nil];

I am wanting to create a filtered NSArray that only contains objects where the NSDictionary matches multiple 'keys' using NSPredicate.

For example:

  • filter the array to only contain the NSDictionary objects that have keys "bill" and "joe" [desired result: new NSArray would contain the first two NSDictionary objects]
  • filter the array to only contain the NSDictionary objects that have keys "joe" and "jenny" [desired result: new NSArray would contain the last two NSDictionary objects]

Can anyone please explain the format of the NSPredicate to achieve this?

Edit: I can achieve a similar outcome to desired NSPredicate using:

NSMutableArray *filteredSet = [[NSMutableArray alloc] initWithCapacity:[data count]];
NSString *keySearch1 = [NSString stringWithString:@"bill"];
NSString *keySearch2 = [NSString stringWithString:@"joe"];

for (NSDictionary *currentDict in data){
    // objectForKey will return nil if a key doesn't exists.
    if ([currentDict objectForKey:keySearch1] && [currentDict objectForKey:keySearch2]){
        [filteredSet addObject:currentDict];
    }
}

NSLog(@"filteredSet: %@", filteredSet);

I'm imagining NSPredicate would be more elegant if one exists?


回答1:


they only way I know is to combine two conditions like "'value1' IN list AND 'value2' IN list"

self.@allKeys should return all the keys of the dictionary (self is each dictionary in your array). If you don't write it with the prefix @ then the dictionary will just look for a key that is "allKeys" instead of the method "- (NSArray*) allKeys"

The code:

NSArray* billAndJoe = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ IN self.@allKeys AND %@ IN self.@allKeys" , @"bill",@"joe" ]];


NSArray* joeAndJenny = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ IN self.@allKeys AND %@ IN self.@allKeys" , @"joe",@"jenny" ]]



回答2:


Since a dictionary just returns nil if you ask for a value of a non-existing key, it is enough to specify that the value should be non-nil. A format like the following should cover your first case:

[NSPredicate predicateWithFormat: @"%K != nil AND %K != nil", @"bill", @"joe"]

The second case, with "joe" and "jenny" follows a similar pattern, of course.



来源:https://stackoverflow.com/questions/10980618/using-nspredicate-to-filter-based-on-multiple-keys-not-values-for-key

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!