Sunil
Sunil

Reputation: 107

how to evaluate a NSDictionary in NSPredicate

I have a dictionary having two arrays, the dictionary is

NSDictionary * StudentDetails = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:StudentIDs,StudentNames, nil] forKeys:[NSArray arrayWithObjects:@"ID",@"NAME", nil]];

and the two arrays are

NSArray * StudentIDs = [NSArray arrayWithObjects:@"07bg1234",@"07ac1234", nil];
NSArray * StudentNames = [NSArray arrayWithObjects:@"aaaaaaa",@"bbbbb", nil];

and I tried predicates to retrieve array values as

NSString * searchStr = @"07bg1234";

    NSPredicate * fileExtPredicate01 = [NSPredicate predicateWithFormat:@"SELF IN %@", StudentIDs];

    if (([fileExtPredicate01 evaluateWithObject: searchStr]== YES)) {
        NSLog(@"Student ID: %@ Exists",searchStr);
    }
    else {
        NSLog(@"Student ID: %@ not Exists",searchStr);
    }

up to this it is working fine.... when i tried to get dictionary values as

NSPredicate * fileExtPredicate02 = [NSPredicate predicateWithFormat:@"SELF IN %@", StudentDetails];

    if (([fileExtPredicate02 evaluateWithObject: searchStr]== YES)) {
        NSLog(@"Student Details: %@ Exists",searchStr);
    }
    else {
        NSLog(@"Student Details: %@ not Exists",searchStr);
    }

I'm always getting the o/p as Student Details **** not Exists... How can i get the 'searchStr' is there or not in the dictionary using predicates???? Thank you in Advance

Upvotes: 0

Views: 516

Answers (2)

Jeffery Thomas
Jeffery Thomas

Reputation: 42588

Use @"SELF IN %@.ID".

I build the following passing unit test.

NSArray * StudentIDs = [NSArray arrayWithObjects:@"07bg1234",@"07ac1234", nil];
NSArray * StudentNames = [NSArray arrayWithObjects:@"aaaaaaa",@"bbbbb", nil];
NSDictionary * StudentDetails = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:StudentIDs,StudentNames, nil] forKeys:[NSArray arrayWithObjects:@"ID",@"NAME", nil]];
NSString *searchStr = @"07bg1234";

NSPredicate * fileExtPredicate02 = [NSPredicate predicateWithFormat:@"SELF IN %@.ID", StudentDetails];

XCTAssert([fileExtPredicate02 evaluateWithObject:searchStr]);

Update

To get both ID an NAME, I used.

NSArray * StudentIDs = [NSArray arrayWithObjects:@"07bg1234",@"07ac1234", nil];
NSArray * StudentNames = [NSArray arrayWithObjects:@"aaaaaaa",@"bbbbb", nil];
NSDictionary * StudentDetails = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:StudentIDs,StudentNames, nil] forKeys:[NSArray arrayWithObjects:@"ID",@"NAME", nil]];

NSPredicate * fileExtPredicate02 = [NSPredicate predicateWithFormat:@"SELF IN %@.ID OR SELF IN %@.NAME", StudentDetails, StudentDetails];

XCTAssert([fileExtPredicate02 evaluateWithObject:@"07bg1234"]);
XCTAssert([fileExtPredicate02 evaluateWithObject:@"aaaaaaa"]);

This feels very kludgy to me, and I think there is a better answer using SUBQUERY(), but I'll have to think about that a bit more.


Update 2

So if you can put up with some wonkiness, here is the SUBQUERY() version. The predicate is SUBQUERY(%@, $value, SELF IN $value).@count > 0. SUBQUERY(%@, $value, SELF IN $value) returns an array of matching values and .@count > 0 returns true if there is at least 1 match. Unlike the previous sample, I don't pass StudentDetails. I need to pass StudentDetails.allValues.

NSArray * StudentIDs = [NSArray arrayWithObjects:@"07bg1234",@"07ac1234", nil];
NSArray * StudentNames = [NSArray arrayWithObjects:@"aaaaaaa",@"bbbbb", nil];
NSDictionary * StudentDetails = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:StudentIDs,StudentNames, nil] forKeys:[NSArray arrayWithObjects:@"ID",@"NAME", nil]];

NSPredicate * fileExtPredicate02 = [NSPredicate predicateWithFormat:@"SUBQUERY(%@, $value, SELF IN $value).@count > 0", StudentDetails.allValues];

XCTAssert([fileExtPredicate02 evaluateWithObject:@"07bg1234"]);
XCTAssert([fileExtPredicate02 evaluateWithObject:@"aaaaaaa"]);

Upvotes: 2

vadian
vadian

Reputation: 285082

For a dictionary you need the condition <Item> IN <Key> which corresponds to @"07bg1234" IN @"ID" in your example. The object in evaluateWithObject is the dictionary.

NSPredicate *fileExtPredicate02 = [NSPredicate predicateWithFormat:@"%@ IN ID", searchStr];
if ([fileExtPredicate02 evaluateWithObject: studentDetails] == YES) {
  NSLog(@"Student Details: %@ Exists",searchStr);
}
else {
  NSLog(@"Student Details: %@ not Exists", searchStr);
};

Upvotes: 1

Related Questions