2012-06-11 9 views
10

Tôi đã sau NSArray chứa NSDictionary (s):Sử dụng NSPredicate để lọc dựa trên nhiều phím (KHÔNG giá trị cho key)

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

Tôi muốn tạo ra một NSArray lọc mà chỉ chứa các đối tượng nơi NSDictionary khớp với nhiều 'khóa' bằng NSPredicate.

Ví dụ:

  • lọc mảng chỉ chứa các đối tượng NSDictionary có chìa khóa "hóa đơn" và "joe" [kết quả mong muốn: mới NSArray sẽ chứa các hai đối tượng NSDictionary đầu tiên]
  • lọc mảng chỉ chứa các đối tượng NSDictionary có phím "joe" và "jenny" [kết quả mong muốn: mới NSArray sẽ chứa cuối cùng hai đối tượng NSDictionary ]

Có ai vui lòng giải thích định dạng của NSPredicate để đạt được điều này không?

Edit: tôi có thể đạt được một kết quả tương tự như NSPredicate mong muốn sử dụng:

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); 

Tôi đang tưởng tượng NSPredicate sẽ thanh lịch hơn nếu có?

Trả lời

24

họ chỉ cách tôi biết là kết hợp hai điều kiện như " 'value1' trong danh sách và 'value2' trong danh sách"

tự. @ AllKeys nên trả lại tất cả các phím của từ điển (tự là mỗi từ điển trong mảng của bạn). Nếu bạn không viết nó với tiền tố @ thì từ điển sẽ chỉ cần tìm một chìa khóa đó là "allKeys" thay vì phương pháp này "- (NSArray *) allKeys"

Mã:

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


NSArray* joeAndJenny = [data filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:@"%@ IN [email protected] AND %@ IN [email protected]" , @"joe",@"jenny" ]] 
+0

Anh ta cũng có thể sử dụng '+ andPredicateWithSubpredicates của NSCompoundPredicate:' thay vì hardcoding chỉ có 2 lựa chọn. –

+0

Cảm ơn. Tôi sẽ thử điều này vào buổi sáng. Mã trông giống như những gì tôi muốn! –

+0

Ok .. cuối cùng đã trở lại điều này. Mã hoạt động, chỉ cần đảm bảo rằng nó cấp phát init-ed: 'NSArray * billAndJoe = [[NSArray alloc] initWithArray: [NSArray arrayWithArray: [data filtersArrayUsingPredicate: [NSPredicate predicateWithFormat: @"% @ IN tự. @ AllKeys AND% @ IN tự @ allKeys ", @" hóa đơn ", @" joe "]]]];' –

5

Vì từ điển chỉ trả về nil nếu bạn yêu cầu giá trị của một khóa không tồn tại, đủ để xác định rằng giá trị phải là số không. Một định dạng như sau phải bao gồm trường hợp đầu tiên của bạn:

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

Trường hợp thứ hai, với "joe" và "jenny" theo cùng một kiểu, tất nhiên.