NSPredicate match string by words - ios

I have an array of strings as below:
["Milk","Milkshake","Milk Shake","MilkCream","Milk-Cream"]
and if I search for "milk" then results should be ["Milk","Milk Shake","Milk-Cream"] i.e. search by words.
With the predicate as
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"tagName CONTAINS[c] %#",containSearchTerm];
I am getting all the results from above array. How can I perform match using words ?

You need a “regular expression search” in order to match against word boundaries, that is done with "MATCHES" in a predicate. Here is an example (essentially translated from NSPredicate with core data, search word with boundaries in string attribute to Swift):
let searchTerm = "milk"
let pattern = ".*\\b\(NSRegularExpression.escapedPattern(for: searchTerm))\\b.*"
let predicate = NSPredicate(format: "tagName MATCHES[c] %#", pattern)
This searches for all entries where the tagName contains the given search term, surrounded by a “word boundary” (the \b pattern).

Related

What is syntax for placeholder usage in regular expression in Predicate?

I want to specify my value in regular expression, how can I do it?
What I am doing:
request.predicate = Predicate(format: "entityProperty MATCHES [c] '[^0123]%#'", myValue)
Observing the result, I can say that %# is parsed as a characters in the regex string, no value is placed instead of it
Here is some explanation on usage of regular expressions with predicates, but no information about placeholders for values
Your Solution would work for:
myValue is representing valid regex pattern.
myValue may not contain single quotes (').
If myValue may contain single quote, this would work:
request.predicate = NSPredicate(format: "entityProperty MATCHES [c] %#", "[^1234]" + myValue)
And if myValue is not a regex pattern and may contain some meta-characters, you may need to write something like this:
request.predicate = NSPredicate(format: "entityProperty MATCHES [c] %#", "[^1234]"+NSRegularExpression.escapedPattern(for: myValue))
Anyway, you need to remember:
Single or double quoting variables (or substitution variable strings)
cause %#, %K, or $variable to be interpreted as a literal in the
format string and so prevent any substitution.
Parser Basics (Predicate Programming Guide)
(I used NSPredicate as Predicate is not available in Xcode 8 beta 6.)
request.predicate = Predicate(format: "entityProperty MATCHES [c] '[^0123]\(myValue)'")
Solution:
instead of %# placeholder use string substitution:
"prefixSomeText\(myValue)suffixSomeText"

NSPredicate Exact Match with String

hello I am working on swift. I need to know how can I find results which matches the exact string. Here's my code
let userID: String = String(sender.tag)
// Create a Predicate with mapping to trip_id
let filterByRequest: NSPredicate = NSPredicate(format: "%K.%K CONTAINS[c] %#", "ProductRequest", "user_id", userID)
// Filter your main array with predicate, resulting array will have filtered objects
let filteredArray: [AnyObject] = self.array.filteredArrayUsingPredicate(filterByRequest)
The problem is If user id is 69 it shows results of users whose id is 69, 6, and 9.
I googled but I find some answers closed to my question but they were all in objective C.
Use MATCHES in predicate as following :
let filterByRequest: NSPredicate = NSPredicate(format: "%K.%K MATCHES %#", "ProductRequest", "user_id", userID)
Hope it helps..
To test for exact equality, simply use == instead of CONTAINS:
NSPredicate(format: "%K.%K == %#", ...)
This can also be combined with [c] for case-insensitive equality:
NSPredicate(format: "%K.%K ==[c] %#", ...)

NSPredicate - Return inexact matches

In my app I allow users to search for vehicles by make/model using a textfield keyword search. Here is my predicate:
if (self.keywordSearch.text.length > 0) {
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"fields.make CONTAINS[cd] %# OR fields.model CONTAINS[cd] %#", self.keywordSearch.text, self.keywordSearch.text];
self.vehicleArray = [[self.vehicleArray filteredArrayUsingPredicate:predicate] mutableCopy];
}
The problem is that if the Vehicle make/model is 'Ford F-150' and the user searches F150, or F 150, the vehicle isn't included in the results. It only returns if they search F-150 or f-150.
Is there a way to make sure these inexact matches are returning?
I suggest using regular expressions for this. You can either use a regular expression literal inside the NSPredicate format (described here: https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/Predicates/Articles/pUsing.html ) or you can iterate the array manually and use an NSRegularExpression for comparing the strings.

Escape nonbreaking space as argument in NSPredicate

I want to filter out empty records, but I am not able to remove the records which has no data but a series of space..
I have a Entity A with attribute "name" . I want to query all those objects of Entity A which has some text value for attribute name and not "series of space",In other words I need to incorporate this in the query -->
[name stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet].length!=0
But all I could was check the length of string INCLUDING the whitespace which is not right.
I am using-->
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"name!=' ' or name.length!=0 "];
Your suggetions are welcome.
you can trim the string and check for the lenght of the string like this:
NSString *trimmedString = [aRecordString stringByTrimmingCharactersInSet:[[NSCharacterSet characterSetWithCharactersInString:#" "]]];
if (trimmedString.lenght > 0) {
// the string if valid or at least is not just a spaces string
}
else {
// the string is not valid or was just a spaces string
}
so if you want to apply this check in a predicate you can use a predicate with block:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
// do your checks here and return TRUE or FALSE if the ovject match your criteria
}];
If you're trying to remove objects where a specific string attribute contains only spaces, use a regex-based predicate, and then delete whatever objects you find.
A fetch with a predicate like this would find all of those objects:
NSPredicate *reqPredicate = [NSPredicate predicateWithFormat:#"attributeName matches ' +'"];
Once found, use -[NSManagedObjectContext deleteObject:] to delete the resulting objects.

How can I filter UITableView with two predicates in IOS

I have tableView with searchDisplayController. In this TV i have to arrays (first/last names)
I can filter this values by names, using predicate, with this code
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.firstName beginswith[cd]%#",searchString];
self.filteredAllClients = [AllClients filteredArrayUsingPredicate:predicate];
Can i filter this arrays using two predicates?
For example: I have names (Jack Stone, Mike Rango)
If I`m entering 'J' and i should get filtered array - Jack Stone
But if I'm entering 'R' and i should get filtered area - Mike Rango?
Yes, like this...
NSPredicate *firstNamePredicate = [NSPredicate predicateWithFormat:#"self.firstName beginswith[cd]%#",searchString];
NSPredicate *lastNamePredicate = [NSPredicate predicateWithFormat:#"self.lastName beginswith[cd]%#",searchString];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:#[firstNamePredicate, lastNamePredicate]];
self.filteredAllClients = [AllClients filteredArrayUsingPredicate:compoundPredciate];
This will then show all people whose first names begin with the search OR whose last names begin with the search.
I prefer using this format to using the ORs and ANDs in a single predicate as it makes the overall code more readable.
This can also be used to get the NOT of a predicate.
You can also easily get confused if you have compound predicates built in a single predicate.

Resources