Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
586 views
in Technique[技术] by (71.8m points)

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

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?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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" ]]

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...