I extract data from a NSMutableArray using NSPredicate:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF MATCHES %#", value];
NSArray *results = [array_to_search filteredArrayUsingPredicate:predicate];
When I use:
NSLog(#"%#", results);
I get:
({pub_id = 102 "pub_name" = "some publisher" city = "Peshawar"});
I would like to extract values of all 3 items pub_id, pub_name, city.
What's being returned is an array containing 1 object (which denoted by the curly braces {} means a dictionary). To extract each of the three components, you can do:
NSString *pub_id = [[results objectAtIndex:0] valueForKey:#"pub_id"];
NSString *pub_name = [[results objectAtIndex:0] valueForKey:#"pub_name"];
NSString *city = [[results objectAtIndex:0] valueForKey:#"city"];
Bear in mind that this solution is only suitable for the example you've provided. If the query ever returns more than 1 object in the array, you'll need to use enumeration/for loop to read the results.
I have understood that you want to get those three objects separately, isn't it?
In case I am right:
NSLog(#"PUBID: %d \n PUBNAME: %# \n CITY: %#", [[results objectAtIndex:0] intValue], [results objectAtIndex:1], [results objectAtIndex:2]);
This code should print
PUBID: 102
PUBNAME: some publisher
CITY: Peshawar.
So your result from
[array_to_search filteredArrayUsingPredicate:predicate];
is another array and you can use that with objectAtIndex:
To get all the values from a dictionary into an array do:
[dictionary allValues];
The object you get out of the array using the prodicate is apparently an NSDictionary. Use the following code:
NSString *city = [[results objectAtIndex:0] valueForKey:#"city"];
et cetera.
Related
My NSMutableArray contains some strings as elements. One of the element is repeated many times at different indexes in the array. For example [#"", #"1,2,3",#"",#"5,3,2,1",#""].
I want to remove all the elements with value #"" from the mutable array. I tried following ways but couldn't get the solution.
Using For loop:
for(id obj in myMutableArray)
{
if([obj isEqualToString:#""])
{
[myMytableArray removeObject:obj];
}
}
Using dummy mutable array called nextMutableArray
for(id obj in myMutableArray)
{
if([obj isEqualToString:#""])
{
continue;
}
else [nextMutableArray addObject:obj];
}
In both the ways, elements (#"") at other indexes are removed but not at the index 0 (first object). What could be the possible reason? Is there any way to remove all the elements that contain string #"" from the mutable array?
one option is to filter your array using predicates:
NSArray *someArray = #[#"", #"1,2,3", #"", #"5,3,2,1", #""];
NSLog(#"%#", someArray);
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF != ''"];
NSArray *filteredArray = [someArray filteredArrayUsingPredicate:predicate];
NSLog(#"%#", filteredArray);
No Need of For loop. Simply use this.
[mutableArray removeObjectIdenticalTo:#""];
If you want to remove duplicate entries from an array, You can use NSSet Class.
NSSet did not accept duplicate/s value.
NSMutableArray *arrTest=[[NSMutableArray alloc]initWithObjects:#"", #"1,2,3",#"",#"5,3,2,1",#"", nil];
NSSet *set = [NSSet setWithArray:arrTest];
arrTest = [[set allObjects] mutableCopy];
or
You can do like this:
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id str, NSDictionary *unused) { return ![str isEqualToString:#""]; }];
arrTest = [[arrTest filteredArrayUsingPredicate:predicate]mutableCopy];
This is fast and simple way.
I have two arrays and I'm trying to filter the first (array1) with a matching property that exists in a second array (array2). The first array is a dictionary array with key 'name'. The second array is an array of objects with property 'name'. Is it possible to filter contents of 'array1' and display only those that have a matching 'name' found in 'array2'?
I've tried:
NSPredicate *pred = [NSPredicate predicateWithFormat:#"name == #%",self.array2];
NSArray *results = [array1 filteredArrayUsingPredicate:pred];
NSLog(#"The results array is %#", results);
Rather than '==' I've tried a mix of 'IN' and '#K' and 'self' but it either crashes or results are 0.
NSPredicate *pred = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
return [[array2 valueForKey:#"name"] containsObject:[evaluatedObject objectForKey:#"name"]];
}];
This should work with IN:
NSArray *matchSet = [self.array2 valueForKey:#"name"];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"name IN #%",matchSet];
Typed in Safari.
https://developer.apple.com/library/archive/documentation/Cocoa/Conceptual/Predicates/Articles/pSyntax.html#//apple_ref/doc/uid/TP40001795-215891
Here's a quick example of how you could accomplish this:
int main(int argc, const char * argv[])
{
#autoreleasepool {
NSArray *arrayOne = #[#{#"name": #"Alvin"}, #{#"name": #"Brian"}, #{#"name": #"Charlie"}];
BMPPerson *alvin = [[BMPPerson alloc] initWithName:#"Alvin"];
BMPPerson *charlie = [[BMPPerson alloc] initWithName:#"Charlie"];
NSArray *arrayTwo = #[alvin, charlie];
NSArray *values = [arrayTwo valueForKey:#"name"];
NSMutableArray *filteredValues = [NSMutableArray array];
[arrayOne enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString *name = [obj valueForKey:#"name"];
if ([values containsObject:name]) {
[filteredValues addObject:name];
}
}];
NSLog(#"%#", filteredValues);
}
return 0;
}
In the example, arrayOne is an NSArray of NSDictionary objects. Each object has a key of name.
The objects contained in arrayTwo are a basic NSObject subclass that has a name property.
To get the values of the name properties for all of the objects in arrayTwo we make use of the key-value coding method -valueForKey: which calls -valueForKey: on each object in the receiver and returns an array of the results.
We then create an NSMutableArray to hold the filtered results from arrayOne.
Next we enumerate the objects in arrayOne using the -enumerateObjectsUsingBlock: method. In this example, we know that the obj argument is an NSDictionary that has a key of name. Instead of casting to an NSDictionary and calling -objectForKey: we can simply call -valueForKey: and store the value in our local variable name. We then check to see if name is in the values array and if it is, add it to our filteredValues.
I have a NSArray of NSDictionary.
One of the keys of the NSDictionary contains a NSArray of strings.
Is there a way that I can use NSPredicate to find a specific strins in that Array of strings?
Thanks :)
Also: This work great, but not for sublevelArray
predicate = [NSPredicate predicateWithFormat:#" %K LIKE[cd] %#", sKey, sLookForString];
Just replace LIKE with CONTAINS in your format string. For example, given this array:
NSArray *dogs = #[#{#"name" : #"Fido",
#"toys" : #[#"Ball", #"Kong"]},
#{#"name" : #"Rover",
#"toys" : #[#"Ball", #"Rope"]},
#{#"name" : #"Spot",
#"toys" : #[#"Rope", #"Kong"]}];
...the following predicate can be used obtain a filtered array containing only the dictionaries where the value for the key toy is an array that contains the string Kong.
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"%K CONTAINS[cd] %#", #"toys", #"Kong"];
On NSArray you can use filteredArrayUsingPredicate:, on NSDictionary use enumerateKeysAndObjectsUsingBlock: and then for each value do either a filteredArrayUsingPredicate: if it is an NSArray or you can use evaluateWithObject: using the predicate itself.
If you want to filter the array of dictionaries based on the array of strings, you can use -predicateWithBlock to filter the array, as shown in the code below:
- (NSArray *)filterArray:(NSArray *)array WithSearchString:(NSString *)searchString {
NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSDictionary *dictionary = (NSDictionary *)evaluatedObject;
NSArray *strings = [dictionary objectForKey:#"strings"];
return [strings containsObject:searchString];
}];
return [array filteredArrayUsingPredicate:predicate];
}
Normally, if I have an NSArray of just NSString's, I can use the NSArray's method:
- (NSString *)componentsJoinedByString:(NSString *)separator
to get a String (like "John,David,Peter"). However, if I have an NSArray of Core Data Entity objects and I just need to to get 1 attribute within (say, the "name" attribute only of each entity object), what is the easiest way to do this?
The Core Data entity object can have many attributes (name, phone, birthdate), but I just want a string like "John,David,Peter".
The following will do a fetch for only the name properties of the Person objects:
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Person"];
request.propertiesToFetch = #[#"name"];
request.resultType = NSDictionaryResultType;
NSArray *array = [managedObjectContext executeFetchRequest:request error:nil];
NSString *names = [[array valueForKey:#"name"] componentsJoinedByString:#","];
NSLog(#"%#", names);
You need to set the resultType to NSDictionaryResultType otherwise it will ignore propertiesToFetch. The result from the fetch is an array of Dictionaries. Using valueForKey and componentsJoinedByString will create a single string out of all the names.
Your best option is the straightforward one of building up a NSMutableString by iterating over the items in you array and asking each one for its name to use in appendString:. You could add a description method to the entity object and then use the method you mentioned but description is used for other things and would probably cause conflicts.
// Assuming you have the list of entities - NSArray *entityObjects
NSMutableString *nameAttributes = [[NSMutableString alloc] init];
for(int i = 0; i < [entityObjects count]-1; i++){
[nameAttributes appendString:[NSString stringWithFormat:#"%#, ", [entityObjects objectAtIndex:i].name]];
}
[nameAttributes appendString:[NSString stringWithFormat:#"%#", [entityObjects lastObject].name]];
If you have an NSArray *objects of Core Data objects, each of which has a name attribute, then you can use
NSArray *names = [objects valueForKey:#"name"];
to get a new array with all the names, which you can then concatenate with
NSString *allNames = [names componentsJoinedByString:#","];
You can simply do like that,
NSString *toCollectString =#"";
for(int k =0;k<self.arrayHoldingObjects.count;k++)
{
ModelName *model = [self.arrayHoldingObjects objectAtIndex:k];
NSString *str = model.name;
toCollectString = [toCollectString stringByAppendingString:str];
}
You will get the names in toCollectString.
I want to get strings that have specific length in NSArray.
The array has many elements and I don't want to use fast enumeration.
Is there a possible way?
This works like a charm:
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self.length == %d", lenght];
NSArray *filtered = [array filteredArrayUsingPredicate:predicate];
No matter what you do you will be using fast enumeration whether you realize it or not. However, have you considered using an NSPredicate object and the filteredArrayWithPredicate method?
NSArray *yourArray = [[NSArray alloc] initWithObjects:#"Apple, Orange, Grapes, Cherry, nil"];
for(NSString *element in yourArray){
if(element.length==yourLength){
[filteredArray addObject:element];
}
}
NSLog(#"Filtered array now contains the elements with length %d", yourLength);
NSLog(#"Filtered array--%#", filteredArray);