1

I have a string say, "0,1,2,3,4,5,6,7,8,9,10,11" (Assumed to be months index string) in my Core Data. I want to use a predicate to fetch whether that field contains a number say, string contains '0'.

We cannot use 'CONTAINS' since '0' is also present in '10'. I need to fetch the object using NSPredicate to avoid loops from Core Data.

Update: I just want to test whether '0,1,2,3,4,5,6,7,8,9,10,11' contains '0' or not using NSPredicate.

Solved

The "MATCHES" operator of NSPredicate can be used to compare against a regular expression:

NSString *searchTerm = @"0";
NSString *regex = [NSString stringWithFormat:@"(.*,)?%@(,.*)?", searchTerm];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"strIndex MATCHES %@", regex];

This worked fine for me. Thank you @skagedal for the suggestion. I got this answer from Form NSPredicate from string that contains id's.

shim
  • 9,289
  • 12
  • 69
  • 108
Sudhin Davis
  • 2,010
  • 13
  • 18
  • Check this out [http://stackoverflow.com/questions/11597508/nspredicate-exact-match-with-string](http://stackoverflow.com/questions/11597508/nspredicate-exact-match-with-string) – Gandalf Jan 04 '16 at 07:08
  • make your string 00,01,02,03,04,05,06,07,08,09,10,11,12... – Shubham bairagi Jan 04 '16 at 07:18
  • 2
    Why don't you have a Months entity and then have a to-many relationship from your entity to MOnths? – bbum Jan 04 '16 at 07:29

3 Answers3

1

@bunty's answer is directly correct, but there is a meta answer.

You should probably have a Months entity that contains the 12 months of the year in the data store. Then, have a one-to-many (ordered or not depending on needs) relationship from the thing that contains that string to the Months entity.

Then, you simply follow the relationship (i.e. myThing.months) to fetch the months that the entity needs.

For large databases, fetches using string matching predicates are going to be quite slow and it really is a bit of anti-pattern.

bbum
  • 162,346
  • 23
  • 271
  • 359
0

You can check numbers separated by comma by using regular expression as below:

NSString *str = @"0,1,2,3,4,5,6,7,8,9,10,11";
NSString *regex = @"(\\d+)(,\\s*\\d+)*";
NSPredicate *myTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];

if ([myTest evaluateWithObject: str])
    NSLog(@"matched");
else
    NSLog(@"not matched");

So use this predicate while fetching data from core data with field name as below:

NSError* error = nil;
NSString *regex = @"(\\d+)(,\\s*\\d+)*";
NSManagedObjectContext *context = [self managedObjectContext];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"TableName" inManagedObjectContext:context];
[fetchRequest setEntity:entity];

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"MonthFieldName MATCHES %@", regex];
[fetchRequest setPredicate:predicate];
NSArray* arrRecords = [context executeFetchRequest:fetchRequest error:&error];
bunty
  • 629
  • 5
  • 8
0

As bunty writes, you can use regular expressions. If I understand the question, you want a predicate that looks for a specific string of digits – but only if not directly preceded or followed by other digits. This can be achieved with what in regular expressions is called look-behind and look-ahead assertions. More specifically, negative look-behind/look-ahead assertions.

Take a look at the syntax for regular expressions used by NSPredicate. To search for the number 1, without also finding 11 and 10, use the regular expression:

(?<!\d)1(?!\d)

So you can build your Core Data predicate with something like:

NSString *month = @"11"; // the number you're looking for
NSString *regex = [NSString stringWithFormat:@"(?<!\d)%@(?!\d)", month];
NSPredicate *myTest = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regex];

This will not be a very effective search, but if that's what your Core Data model looks like and you can't easily change it, it just might work fine. If you can, I'd go with bbum's suggestion and reorganize your model.

skagedal
  • 2,323
  • 23
  • 34
  • Regular Expression is a Good choice and I hope it is the only Solution for my situation. Thank you so much for the suggestion. in my case the expression you provided didnot work. But I got a similar question from http://stackoverflow.com/questions/14932595/form-nspredicate-from-string-that-contains-ids?rq=1. And that worked fine for me. – Sudhin Davis Jan 05 '16 at 06:07