How can I filter the array of NSDictionarys and NSDictionarys?

I have an array that consists of several NSDictionaries with keys:

  • NSString *name
  • NSString *ID
  • NSDictionary *phoneNumbersDict

Now I want to filter this array to find one that has the key phoneNumbersDict @"keyIAmLookingFor" and the value @"valueIAmLookingFor" .

 NSMutableArray *addressBookPhoneIndividuals = [NSMutableArray array]; for (int i = 0; i < x; i++) { [addressBookPhoneIndividuals addObject:@{ @"name" : @"...", @"ID" : @"...", @"phoneNumbers" : @{...} }]; } 
+7
source share
4 answers
 NSString *keyIAmLookingFor = @"work"; NSString *valueIAmLookingFor = @"444-567-9019"; NSArray *addressBookPhoneIndividuals = @[ @{ @"name" : @"Mike Rowe", @"ID" : @"134", @"phoneNumbers" : @{ @"work" : @"123-456-8000", @"school" : @"647-5543", @"home" : @"123-544-3321", } }, @{ @"name" : @"Eric Johnson", @"ID" : @"1867", @"phoneNumbers" : @{ @"work" : @"444-567-9019", @"other" : @"143-555-6655", } }, @{ @"name" : @"Robot Nixon", @"ID" : @"-12", @"phoneNumbers" : @{ @"work" : @"123-544-3321", @"school" : @"123-456-8000", @"home" : @"444-567-9019", } }, ]; NSString *keyPath = [@"phoneNumbers." stringByAppendingString:keyIAmLookingFor]; NSPredicate *predicate = [NSComparisonPredicate predicateWithLeftExpression:[NSExpression expressionForKeyPath:keyPath] rightExpression:[NSExpression expressionForConstantValue:valueIAmLookingFor] modifier:NSDirectPredicateModifier type:NSEqualToPredicateOperatorType options:0]; NSArray *result = [addressBookPhoneIndividuals filteredArrayUsingPredicate:predicate]; 

This will return an array containing the "Eric Johnson" dictionary.

I like to recommend NSComparisonPredicate when doing any complex matching. See options for modifier, type, and parameters. There are good engines built into them, including regular expressions and case insensitivity. In any case, this is probably not necessary here, so you can replace the following:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"%K = %@", keyPath, valueIAmLookingFor]; 

If you only care about the first result, you can generally skip the keyPath / predicate business:

 for (NSDictionary *individualDict in addressBookPhoneIndividuals) { NSDictionary *phoneNumbers = [individualDict objectForKey:@"phoneNumbers"]; NSString *possibleMatch = [phoneNumbers objectForKey:keyIAmLookingFor]; if ([possibleMatch isEqualToString:valueIAmLookingFor]) { return individualDict; } } return nil; 
+6
source

You can use NSPredicate to filter your array. Something like the following:

 NSPredicate *predicate = [NSPredicate predicateWithFormat:@"phoneNumbers.keyIAmLookingFor == %@", @"valueIAmLookingFor"]; NSArray *matches = [addressBookPhoneIndividuals filteredArrayUsingPredicate:predicate]; 
+5
source

I don’t quite understand how you want to filter your array, but one simple approach that I often use is block filtering:

 NSIndexSet* filteredIndexes = [addressBookPhoneIndividuals indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop){ NSString *name = [obj objectForKey:@"name"]; NSString *ID = [obj objectForKey:@"ID"]; NSDictionary *phoneNumbersDict = [obj objectForKey:@"phoneNumbersDict"]; return [[phoneNumbersDict objectForKey:@"keyIAmLookingFor"] isEqualToString:@"valueIAmLookingFor"]; }]; NSArray* filteredArray = [addressBookPhoneIndividuals objectsAtIndexes:filteredIndexes]; 

Does it help?

+1
source

you can use

 i. –allKeysForObject: ii. –objectForKey: iii. –valueForKey: iv. –keysOfEntriesPassingTest: v. –keysOfEntriesWithOptions:passingTest: 

You can also upgrade to NSPredicateFilter.

0
source

All Articles