Filter an array with other array - ios

I've got 2 arrays:
array1 contains objects of type object1. object1 has a property id.
array2 contains objects of type object2. object2 has a property object1Id.
I know, that array2 contains objects with ids which always are in array1, but array1 can have more (or equal) objects.
To show it:
So to simplify: array1 has all objects, array2 has new objects. How to get an array with old objects..? I'm trying to do it with predicate, but it feels odd to do a loop and insert each object1Id to the predicate. Is there any other option? How to do it properly?

You can use a predicate, and you don't need a loop if you use KVC.
Get the array of ids that should be excluded:
NSArray *excludeIds = [array2 valueForKey#"object1Id"];
Create the predicate:
NSPredicate *filterPredicate = [NSPredicate predicateWithFormat:#"NOT (id IN %#)", excludeIds];
Then filter:
NSArray *oldObjects = [array1 filteredArrayUsingPredicate:filterPredicate];

It looks like you are trying to perform a set operations. What can be helpful is NSMutableSet class. Use setWithArray to create sets. Then use methods like:
unionSet:
minusSet:
intersectSet:
setSet:
To get subsets that match your criteria.
Source: NSMutableSet Class Reference
Hope it helps.

NSArray* oldIds = [array2 valueForKeyPath:#"object1Id"];
NSPredicate* predicate = [NSPredicate predicateWithFormat:#"NOT (id IN %#)", oldIds];
NSArray* objects = [array1 filteredArrayUsingPredicate:predicate];

Related

Order a pre-defined string array in order

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).

NSPredicate String to get n'th item in array

I cannot find a way to get the nth item in an array using an NSPredicate string. For example:
//You cannot touch or modify the code inside this method. You can only use the predicate string param to filter the array.
- (NSArray *)filterUsingNSPredicate:(NSString *)PredicateString
{
NSArray *array = #[
#"firstItem",
#"secondItem",
#"thirdItem",
#"fourthItem",
];
NSPredicate *pred = [NSPredicate predicateWithFormat:PredicateString];
NSArray *filtered = [array filteredArrayUsingPredicate:pred];
NSLog(#"This is the second item in the array! %#",filtered); //Thats the only thing in the array.
return filtered;
}
If you want to get an item, you don't receive an NSArray, because you will only receive an object.
You can use NSPredicate to search by name of an object in your array. But what you say, that is not what you want.
You can use [array objectAtIndex:index];, that returns the object in the position you indicate in index.
If you want the index of an object, you can use [array indexOfObject:object];, that returns the index of the object.
Predicates don't know about array indexes. They only know about the single object that they're presented with at any one time, and whether that object makes the predicate true or false.
The way you're presenting this problem in the comments makes absolutely no sense. If you can get a filtered version of the array, then you can get the array. Here's how you use the method you show to do so:
NSArray * fullList = [theAPI filterUsingNSPredicate:#"TRUEPREDICATE"];
TRUEPREDICATE is a special value for predicate strings that always evaluates to true. When you filter an array with that predicate, the result will be identical to the original.
You now have a reference to the array, and can index into it as you would normally.
You can create predicate with block https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSPredicate_Class/#//apple_ref/occ/clm/NSPredicate/predicateWithBlock%3A like this to get 6-th element (at index 5 counting from 0):
__block NSInteger index = 0;
NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary<NSString *, id> *bindings)(
return index++ == 5;
)];

How to use NSPredicate with Multidimensional array (where the predicateFormat exists at valueForKeyPath)

I have an array where the 'id' on which i want to filter the array exists at valueForKeyPath 'objectId' of each of its dictionaries. How to compare the predicates in ValueForKeyPath.
Currently.. this predicate
NSPredicate * objIdPredicate = [NSPredicate predicateWithFormat:#"objectId = %#",obj];
NSArray * oneOrder = [array filteredArrayUsingPredicate:objIdPredicate];
is considering key and values of the array elements, not the ones at their ValueForKeyPath=#"objectId"
Use "self"in your code to get the array element's valueForKeyPath
NSPredicate *objIdPredicate =[NSPredicate predicateWithFormat:#"(self.objectId = %#)",obj];
`

Check if an object exist in a NSMutableArray of NSDictionary

i have an NSMutableArray that contains some NsDictionary with NSstring for differents Keys.
Somethings like:
NSDictionary *ExempleDictionary = [NSDictionary dictionaryWithObjectsAndKeys:[Date objectAtIndex:sender.tag],#"DATE",[Time objectAtIndex:sender.tag],#"TIME", nil];
I'd like to check if a particular object with DATE=xxx && TIME=xxx exist in the Array.
Any idea?!
You can do the search with NSPredicate:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF.DATE=%# AND SELF.TIME=%#", dateVal, timeVal];
NSArray *filteredArray = [myArray filteredArrayUsingPredicate:predicate];
filteredArray contains an NSArray of all NSDictionary objects matching the specified date and time condition. You can retrieve the matching objects by iterating the filtered array.
You can use NSArray's containsObject: (if you have a reference to the dictionary laying around) or indexOfObjectIdenticalTo: (if you want to check if an element identical to the one you are passing -but not necessarily the same object- is in the array).
Both are explained in the docs:
containsObject
indexOfObjectIdenticalTo

NSPredicate find object with attribute in NSSet

I have an NSMangedObject that contains NSSet of other NSManagedObjects.
I need to check if these objects has an value in NSSet and then return them.
I use MagicalRecord for fetching data.
So I need something like this:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"stringObjects contains %#", string];
So if NSSet stringObjects contains some string that I am looking for so then return object I have requested.
One note here: stringObjects (name just for example it represent my NSSet) it is NSSet that contains NSManagedObjects, so I need to search them by some id (for example string_id attribute).
So then model looks like this
NSSet *set = MainObject.stringObjects;
NSString *string_id_for_first_object = [[[set allObjects] objectAtIndex:0] string_id];
Just for better understanding relationship.
But the question is about how can I create predicate to check if NSSet contains needed id.
If I understand your question correctly, stringObjects is a to-many relationship
from one entity A to another entity B, and B has an attribute string_id.
To find all A objects that are related to any B object with the given string id, use:
NSString *stringId = …; // The string that you are looking for
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ANY stringObjects.string_id == %#", stringId];

Resources