Search code examples
objective-ccocoa-touchnsdictionarynspredicatefoundation

NSPredicate to check if attribute of object exits, if it does, get it


I'm not even sure of this is possible, but if it is, it could surely help.

I have an NSArray of NSDictionaries.

Each dictionary has certain keys (obviously).

Dict{ 
 Title: WBCCount
 Cat: Lab
}
Dict{
 Title: HbM
 Cat: Lab
 Sex: Male
}
Dict{
 Title: HbF
 Cat: Lab
 Sex: Female
}
Dict{
  Title: PC_Count
  Cat: CBC
  Sex: Female
}

I wanted to filter array with dictionaries that have Cat = 'Lab' and IF Sex as a key is present in the dictionary object, get the one with Male.

In short, I cannot put together a

predicateWithFormate:%@" Cat = Lab AND ( if Sex key is present, Sex = Male";

This would get me an array of WBC, HbM.

I don't know if this is possible, a condition within a predicate, but it would be a life saver if it was as this is how the objects are sent via web API.

Any other way of achiving the goal if not this would also be great.

While we are in the subject of Core Data, this should be simple: I want to have an attribute of the entity to be able to store either NSDate or NSNumber or NSString. Is there an easy way out?


Solution

  • The trick here is that in an NSDictionary, a non-present key just returns nil:

    NSArray *dictionaries = @[
        @{ @"Title": @"T1",  @"Cat":   @"Lab",   @"Sex":   @"Male"   },
        @{ @"Title": @"T2",  @"Cat":   @"C2"                         },
        @{ @"Title": @"T3",  @"Cat":   @"Lab",   @"Sex":   @"Female" },
        @{ @"Title": @"T4",  @"Cat":   @"Lab"                        }
    ];                    
    
    NSPredicate *pred = [NSPredicate predicateWithFormat:@"(Sex == nil OR Sex = 'Male') AND Cat = 'Lab'" ];
    
    NSArray *result = [dictionaries filteredArrayUsingPredicate:pred];