NSPredicate and Regex - objective-c

Can someone please help me with using Regex with NSPredicate?
NSString *regex = #"(?:[A-Za-z0-9])";
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", regex];
if ([pred evaluateWithObject:mystring])
{
//do something
}
testing the above wth mystring - qstring123 doesn't seem to work. I am expecting it to enter the if condition because it supposedly should match the regex.
Besides, I need a regex for alpha numberic allowing commas and spaces.
will this work?
#"(?:[A-Za-z0-9])*(?:,[A-sa-z0-9)*(?:\s[A-sa-s0-9])"
Please help.

From my experimentation, it tries to match the regex against the entire string, and won't match inside a string.
Therefore, the regex [a-zA-Z0-9]+ works, but [a-zA-Z0-9] does not.
With that in mind, you may want to rework your comma-matching predicate, or use a more full-featured regex solution, like the amazingly awesome RegexKit and RegexKitLite.

Related

CoreData NSPredicate MATCHES regex

I have a CoreData table with a field holding a string of a series of numbers separated by commas. I want to be able to run a fetch with a predicate that will match against a given specific number.
For example if fieldName = "12,52,66,89,2,8"
And I want to search for 2, then it should match the second to last number in the string and include that record in the results.
Using the regular expression:
^2|,2,|,2
I have found it working satisfactorily for my test cases, testing it using this site for example: https://www.regexpal.com/
However, when I pass this into an NSPredicate for a NSFetchRequest, I can't get it to match
NSNumber *val = #2;
NSString *regex = [NSString stringWithFormat:#"^%#|,%#,|,%#", val, val, val];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"fieldName MATCHES %#", regex];
Replacing the MATCHES with a CONTAINS val makes it work, but of course it will also incorrectly match any occurrence of the digits.
I suspect I am missing something stupid about formatting for CoreData (or regex), but I've tried many variations, and I'm hoping a kind soul reading this will put me out of my misery :)
Disclaimer: I haven't used Objective C. This answer is based on my regex knowledge and some documentation.
MATCHES
The left hand expression equals the right hand expression using a regex-style comparison according to ICU v3 (for more details see the ICU User Guide for Regular Expressions).
That sounds like how Java uses the method "matches" in which case "^2|,2,|,2" can never match the entire string. This differs from regexpal which will always search the text. The regex you would need is more like
.*\b2\b.*
(the ^$ are assumed in Java). Another option is to split the string.

Objective C - NSRange and rangeOfString

I have a little problem with NSRange and rangeOfString. I want to search a substring in a given string which is working fine, but only to find a exact string and theres the problem i need to find a substring which begins always the same and ends always the same. I tried it already with something like that:
match = [strIn rangeOfString: #"truni/begin/*/end"];
But thats not working. So i need a way to to do this. Here is the specific part of the Code in full:
NSRange match;
match = [strIn rangeOfString: #"turni/begin/sHjeUUej/end"];
NSRange range = NSMakeRange(match.location, match.length);
NSString *strOut = [strIN substringWithRange:range];
You see the string "turni/begin/sHjeUUej/end" will always be the same except for the part "sHjeUUej". Hope someone can help me.
Thanks in advance.
Use a regular expression with:
- (NSRange)rangeOfString:(NSString *)aString options:(NSStringCompareOptions)mask
with an option of RegularExpressionSearch.
See ICU User Guide Regular Expressions for information on creating regular expressions.
you can use prefix/suffix
if ([strIn hasPrefix:#"truni/begin/"] && [strIn hasSuffix:#"end"]) {
//match
You can use a simpler solution if you make sure that your string always starts with turni/begin/ and ends with /end.
You can use:
NSString *strOut = [[strIn stringByReplacingOccurrencesOfString:#"turni/begin/" withString:#""] stringByReplacingOccurrencesOfString:#"/end" withString:#""];
With that, you can retrieve the string between the two others with only one line of code and less comparations.

how to validate Zipcode for US or Canada in iOS?

I want to know that is there any way to validate the the zipcode of US or Zipcode of Canada?I have tried to use regex.
Like for US
- (BOOL)validateZip:(NSString *)candidate {
NSString *emailRegex = #"(^{5}(-{4})?$)|(^[ABCEGHJKLMNPRSTVXY][A-Z][- ]*[A-Z]$)";
NSPredicate *emailTest = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", emailRegex];
return [emailTest evaluateWithObject:candidate];
}
but it's not working.Please any body have any idea regarding this validation.if any rest api is there for the validation?Please guide me if possible?
For the US, you have the quantifiers ({5}, {4}, ?) correct but forgot to specify exactly what you're quantifying. You want:
(^[0-9]{5}(-[0-9]{4})?$)
For Canada, according to Wikipedia, the format is A0A 0A0, so I would do:
(^[a-zA-Z][0-9][a-zA-Z][- ]*[0-9][a-zA-Z][0-9]$)
Now, I'd write the complete expression like this, with case insensitivity enabled:
#"^(\\d{5}(-\\d{4})?|[a-z]\\d[a-z][- ]*\\d[a-z]\\d)$"
Frankly, I'm not actually familiar with Objective C or iOS, and sadly I haven't tested the above. However, previously I've seen such posts mention NSRegularExpression, which is missing in your code, but perhaps isn't necessary. Take a look at others' examples to see what other simple errors you might be making. Good luck.
We used this but its only for UK Postcodes. See #acheong87 answer to alter the regex to fit your criteria and other good answers.
NSString *postcodeRegex = #"[A-Z]{1,2}[0-9R][0-9A-Z]?([0-9][ABD-HJLNP-UW-Z]{2}";//WITH SPACES
NSPredict *postcodeValidate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", postcodeRegex];
if ([postcodeValidate evaluateWithObject:postcodeField.text] == YES) {
NSLog (#"Postcode is Valid");
} else {
NSLog (#"Postcode is Invalid");
}
I advise you test the regex first using this great tool http://www.regexr.com
EDIT
Current regex does not support spaces in postcode after further testing. This will fix that issue.
NSString *postcodeRegex = #"[A-Z]{1,2}[0-9R][0-9A-Z]?(\s|)([0-9][ABD-HJLNP-UW-Z]{2}";//WITH SPACES

need help on a simple predicate to match any word in a string to a property

Let's say i want to let user search for my objects using a name property of the objects.
I have no problem if the user only enters one word:
e.g: facial
My predicate will be:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] %#", word];
But what if user enter more than one word separated by space?
I want to do sth like:
NSArray *words = [query componentsSeparatedByString:#" "];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"name CONTAINS[cd] ANY %#", words];
But it doesnt work. Any guidance?
Thanks!
Another way of doing this (and I just learnt this myself as a result of your question) is to use subqueries. Check this SO question for more details. You can use subqueries in the following manner –
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SUBQUERY(%#, $str, SELF CONTAINS[cd] $str).#count != 0", words];
NSLog(#"%#", [array filteredArrayUsingPredicate:predicate]);
This seems to work as I've tested it myself but this could also be the arcane & obscure way that Dave has mentioned as it finds no mention in the Predicate Programming Guide.
The format for a SUBQUERY can be found here. It's the same link that you will find in the question linked earlier.
As you mentioned (correctly) in the comment, you can do this by building a compound predicate predicate, although you'll want to use orPredicateWithSubpredicates, and not the and variant.
That really is the best way to do this. There are others, but they rely on more arcane and obscure uses of NSPredicate, and I really recommend going with the build-a-compound-predicate route.

NSPredicate case-insensitive matching on to-many relationship

I am implementing a search field where the user can type in a string to filter the items displayed in a view. Each object being displayed has a keywords to-many relationship, and I would like to be able to filter the objects based on their keywords. Each keyword object has a name property, so I've set up an NSPredicate to do the filtering that looks like this:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"keywords.name CONTAINS %#", self.searchString];
This works, but the problem is that the search is case-sensitive, so if the keyword has a capital letter but the user types in all lowercase, no matches are found. I've tried the following modification:
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"keywords.name CONTAINS[c] %#", self.searchString];
But that doesn't make any difference in the case sensitivity of the matching. Is there a way to do this case-insensitive matching using just a plain predicate? Or will I need to implement some sort of custom accessor on the keyword class, e.g. write a lowercaseName method and match against a lowercased version of the search string instead?
Addendum:
After further exploration, the workaround of adding a custom accessor works OK for manual use of NSPredicate, but does not work at all when using NSFetchRequest with Core Data, which only works when querying attributes defined in the Core Data model.
If I understand you correctly, you want your predicate to be true whenever any keywords name matches the search string. For this you need to test with the ANY keyword like this:
[NSPredicate predicateWithFormat:#"ANY keywords.name CONTAINS[c] %#", ...];
This will search the keywords and return true if any of those keywords name contains your search string.
I believe the answer is:
[NSPredicate predicateWithFormat:#"keywords.name CONTAINS[cd] %#", self.searchString];
String comparisons are by default case and diacritic sensitive. You can modify an operator using the key characters c and d within square braces to specify case and diacritic insensitivity respectively, for example firstName BEGINSWITH[cd] $FIRST_NAME.
Predicate Format String Syntax
If you is trying to catch only the equals names but with insensitive case, I think it is the best solution
[NSPredicate predicateWithFormat:#"ANY keywords.name LIKE[c] %#", ...];
You helped me a lot. Thanks guys!!!
In my case I did:
[NSPredicate predicateWithFormat:#"ANY name LIKE[c] %#", #"teste"];
If you must match the keyword but the search must be case-insensitive then you should use NSPredicate(format: "keywords.name =[c] %#", self.searchString)
LIKE does not work on string literals.
If you want both case insensitive and wildcard, use this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:[NSString stringWithFormat:#"(name like[c] '*%#*')",#"search"]];