In the following reversedArray has three or more strings such as Salads, Meats Appetizer in order.
However, I want to have Meats always to be the first string in the array.
NSPredicate *predicateMain = [NSPredicate predicateWithFormat:
#"(%K == %#)", #"categoryType", #"main"];
NSPredicate *predicateSide = [NSPredicate predicateWithFormat:
#"(%K == %#)", #"categoryType", #"side"];
NSPredicate *orPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:
[NSArray arrayWithObjects:predicateMain, predicateSide,nil]];
NSArray *filteredArray = [foods filteredArrayUsingPredicate:orPredicate];
NSArray *reversedArray = [[[filteredArray valueForKeyPath:
#"#distinctUnionOfObjects.categoryName"]
reverseObjectEnumerator] allObjects];
I can do it via hardcode but I want to know proper way of handling.
To avoid hardcoding you could write a function to reorder the array with any given string as the first string, and utilize that.
For example:
void yourFunctionName(string firstString, NSArray &array){
//Iterate through array
//Check if you've found a string matching firstString
//Put it at the front by moving everything else down one
//Continue to iterate until you've reached the end of the array
}
Here it would be best to pass the array by reference (using the &) so that you modify the array itself and not just a copy of the array values (what you get when you don't pass by reference).
Related
It is possible to filter an array of strings as follows:
NSArray *array = #[#"honda",#"toyota",#"ford"];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF contains[cd] %#",#"ford"];
NSArray *filtered = [array filteredArrayUsingPredicate:pred];
I want to search an array that contains arrays of two strings by the values for the first of the strings. So for:
NSArray *cars = #[#[#"honda",#"accord"],#[#"toyota",#"corolla"],#[#"ford",#"explorer"]];
I want to search the first dimension (honda, toyota, ford) for #"ford"
Is there a way to tell the predicate I want to search on only the first attribute and return matching elements of the array?
Well here is the pred you need.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF[FIRST] contains[cd] %#", #"ford"];
Here say I have a array of objects with two attributes:
// array of object
NSArray *objects
// object
NSString *primaryTag;
NSArray *secondaryTag;
Since what I want is when the this object contains the givenTag, it could be passed to a new array called results;
Here is my codes:
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"primaryTag == %# || secondaryTag CONTAINS[c] %#", givenTag, givenTag];
results = [objects filteredArrayUsingPredicate:resultPredicate];
It seems that the primaryTag works well, but the secondaryTag doesn't work, can someone help me out. I am not that familiar with NSPredicate filtering. Thanks in advance.
The most efficient way to do that is with a NSCompoundPredicate like so:
NSArray *subPredicates = #[tag1, tag2, tag3];
NSPredicate *compoundPredicate = [NSCompoundPredicate orPredicateWithSubpredicates:subPredicates];
Your question is a little unclear so you might also want:
andPredicateWithSubpredicates
Depending on exactly what the nature of the result set you are looking for.
See Apple Docs here: NSCompoundPredicate Docs
i implemented the following custom class:
#interface CustomObject : NSObject
#property (copy, nonatomic) NSString *primaryTag;
#property (strong, nonatomic) NSArray *secondaryTag;
#end
and overrode it's description method for the NSLog statement to print something we understand:
- (NSString *)description {
return [NSString stringWithFormat:#"primaryTag: %#, secondaryTag: %#", _primaryTag, [_secondaryTag componentsJoinedByString:#", "]];
}
then i created some objects from the custom class and added them to an array:
NSMutableArray *objects = [NSMutableArray array];
CustomObject *obj1 = [CustomObject new];
obj1.primaryTag = #"stringToSearchFor";
obj1.secondaryTag = #[#"notTheStringToSearchFor", #"somethingElse"];
[objects addObject:obj1];
CustomObject *obj2 = [CustomObject new];
obj2.primaryTag = #"differentString";
obj2.secondaryTag = #[#"nothingWeAreLookingFor"];
[objects addObject:obj2];
CustomObject *obj3 = [CustomObject new];
obj3.primaryTag = #"anotherOne";
obj3.secondaryTag = #[#"whoCaresForThisString", #"stringToSearchFor"];
[objects addObject:obj3];
finally i created a string to search for and the predicate:
NSString *givenTag = #"stringToSearchFor";
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"primaryTag == %# || secondaryTag CONTAINS[c] %#", givenTag, givenTag];
when i log out the result i get the correct results:
NSLog(#"%#", [objects filteredArrayUsingPredicate:resultPredicate]);
logs:
(
"primaryTag: stringToSearchFor, secondaryTag: notTheStringToSearchFor, somethingElse",
"primaryTag: anotherOne, secondaryTag: whoCaresForThisString, stringToSearchFor"
)
which is obj1 and obj3. correct! if it does not work for you there's gotta be something else wrong with your code...
If my understanding of the original question is incorrect, please let me know, and I will adjust my answer.
Problem: You have an array of objects with 2 properties. One is primaryTag, which is a string. The second is an array of secondaryTags, which is a collection of strings. You want to filter all objects where either the primaryTag matches, or where the search string matches one of the secondaryTags.
Answer The proper way to match strings is via MATCHES or CONTAINS.
NSPredicate *pPredicate =
[NSPredicate predicateWithFormat:#"%K CONTAINS[cd] %#",
#"primaryTag", searchString];
NSPredicate *sPredicate =
[NSPredicate
predicateWithFormat:#"SUBQUERY(%K, $st, $st CONTAINS[cd] %#).#count > 0",
#"secondaryTags", searchString];
NSCompoundPredicate *searchPredicate =
[NSCompoundPredicate orPredicateWithSubPredicates:#[ pPredicate, sPredicate ]];
How it works: The first predicate is a straightforward match. You can replace CONTAINS with MATCHES, if that better fits the kind of comparison you wish to make. The [cd] suffix means case-insensitive and diacritic-insensitive. It's normal to include those when searching/filtering, but again, it's up to you. Instead of embedding the property name in the predicate format string, I use %K and a replacement parameter. In production code, that replacement parameter would be a constant.
The second predicate is a little trickier. It uses a SUBQUERY() to filter the secondaryTags array, and returns the object as matching if at least one secondary tag matches the search string. SUBQUERY() is a function with 3 parameters. The first is the collection being searched. The second is a temporary variable that represents each item in the collection, in turn; it is used in the 3rd parameter. The 3rd parameter is a regular predicate. Each item in the collection that matches the filter is included in the output of SUBQUERY(). At the end, the matching secondary tags are counted (via #count), and if the count is greater than zero, the original object is considered to have matched, so will be included in the filtered output.
Finally, we combine these two predicates into one searchPredicate, which can now be used to filter your array of objects.
I seen this issue,
My normal approch is to use the NSPredicate twice,
So that I can track the result at every steps:
Option 1:
NSPredicate *resultPredicate1 = [NSPredicate predicateWithFormat:#"primaryTag == %#", givenTag];
results1 = [objects filteredArrayUsingPredicate:resultPredicate1];
NSPredicate *resultPredicate2 = [NSPredicate predicateWithFormat:#"secondaryTag CONTAINS[c] %#", givenTag];
finalResults = [results1 filteredArrayUsingPredicate:resultPredicate2];
Option 2:
Use NSCompoundPredicate to compound multiple filtering. You can easily find many examples on google and stackOverFlow.
Hope this will help,
Thanks
I'm trying to use a predicate to filter objects where an intersection exists between two arrays.
The NSManagedObject has an array(Of Strings) attribute named "transmissions". And there is another array(Of Strings) that will contain words to filter by, named "filters".
I'm not sure how to find if any elements in "transmissions" match any element in "filters".
I've tried
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY SELF.transmission in[c] %#",transmissions];
or
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY transmission in[c] %#",transmissions];
However, core data fetches no results where there should be some.
Try this.
NSPredicate *predicate = nil;
NSMutableArray *predicates = [NSMutableArray new];
for (NSString *transmission in transmissions) {
[predicates addObject:[NSPredicate predicateWithFormat:#"transmission == %#", transmission]];
}
if (predicates.count > 0)
predicate = [NSCompoundPredicate orPredicateWithSubpredicates:predicates];
// make fetch request using 'predicate'
You can use the keyword CONTAINS to check an object exists in a collection.
[NSPredicate predicateWithFormat:#"favouriteFilms CONTAINS %#", film]
I believe the same thing can be achieved with IN by switching the LHS and RHS of the predicate. I have only successfully implemented this functionality using CONTAINS however.
I am trying to filter / search through an NSArray with the text from my UITextfeild.text
If I try to search a match string the filter works but my filtered array always comes out empty as I type the letters in the text-field.
NSArray *testArray = [NSArray arrayWithObjects:#"testmailone#test.com",#"a#test.com",#"b#testing.com",#"h#fgdfgd",#"helloMan#test.com", #"dfsdfsdfsdfsdfs#dsfdfs",nil];
NSPredicate *predicatedString = [NSPredicate predicateWithFormat:#"SELF == %#", self.addHungryPersonTF.text];
NSArray *resultsArrayString = [testArray filteredArrayUsingPredicate:predicatedString];
NSLog(#"resultsArrayString%#",resultsArrayString);
This returns null but if I change the string to match against another set string like so:
NSString *matches = [NSString stringWithFormat:#"testmailone#test.com"];
NSLog
resultsArrayString(
"testmailone#test.com"
)
It then works an the array becomes populated with matched string.
Anyone have any ideas of why it will not search through my NSArray by letter? When I type it should be checking the array correctly?
NSPredicate *predicatedString = [NSPredicate predicateWithFormat:#"SELF CONTAINS %#", self.addHungryPersonTF.text];
//keep this one for get all the strings which contains the substring or string itself
NSPredicate *predicatedString = [NSPredicate predicateWithFormat:#"SELF BEGINS %#", self.addHungryPersonTF.text];
//keep this one for sting starts with the key word
I have to get a particular string from a list of strings using NSPredicate (CoreData). For eg:
if I have the following array from CoreData
Helloworld
helloworld1234
helloworld 12345
from the above list I need only 1 and 3 one as result.
I have tried the following but i get all the three as result
NSPredicate *predicate =[NSPredicate predicateWithFormat:#"contactName CONTAINS [c]%#",[arySeperator objectAtIndex:1]];
NSArray *filteredArray1 = [arrayContacts filteredArrayUsingPredicate:predicate];
Where I am going wrong?
To find all entries that contain the given text as a "whole word", you can use the
predicate "MATCHES" operator, which matches against a regular expression, and the
word boundary pattern \b:
NSString *searchWord = #"Helloworld";
NSString *pattern = [NSString stringWithFormat:#".*\\b%#\\b.*", searchWord];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"contactName MATCHES[c] %#", pattern];
This should also work if you add this predicate to the Core Data fetch request,
instead of filtering an already fetched array of managed objects.
LIKE
The left hand expression equals the right-hand expression: ? and * are allowed as wildcard characters, where ? matches 1 character and * matches 0 or more characters.
NSString *textSearch = #"Raja";
NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:#"firstname LIKE '*%1$#*' OR lastname LIKE '*%1$#*'", textSearch];
You can use below code to get if a string is present in an NSArray:
NSArray* yourArray = [NSArray arrayWithObjects: #"Str1", #"Str2", #"Str3", nil];
if ( [yourArray containsObject: yourStringToFind] ) {
// do found
} else {
// do not found
}