I have an NSArray of objects, which have a property id.
I then have another NSArray with a selection of ids.
I need to get all the objects in the first array which have the ids listed in the second array.
Is it possible to do this without for loops (well 1 for loop is ok, but I'd like to avoid it). I know how to do this with 2 for loops, but this seems very inefficient. So basically I'm looking for the most efficient way.
(The Id is an NSURL btw, so it can't be anything integer specific)
No loops!
NSArray *arrayOfIdentifiers = ...;
NSArray *arrayOfObjects = ...;
NSPredicate *filter = [NSPredicate predicateWithFormat:#"id IN %#", arrayOfIdentifier];
NSArray *filteredObjects = [arrayOfObjects filteredArrayUsingPredicate:filter];
Well, no loops that you write. There are probably loops inside filteredArrayUsingPredicate:.
You need an intersection os sets.
NSMutableSet *set1=[[[NSMutableSet alloc] initWithArray:array1] autorelease];
NSMutableSet *set2=[[NSMutableSet alloc] initWithArray:array2];
[set1 intersectSet:set2];
[set2 release];
NSArray *newArray=[set1 allObjects];
Related
I am having a problem that I think I am overcomplicating.
I need to make either an NSMutableArray or NSMutableDictionary. I am going to be adding at least two objects like below:
NSMutableArray *results = [[NSMutableArray alloc] init];
[results addObject: [[NSMutableArray alloc] initWithObjects: [NSNumber numberWithInteger:myValue01], #"valueLabel01", nil]];
This gives me the array I need but after all the objects are added I need to be able to sort the array by the first column (the integers - myValues). I know how to sort when there is a key, but I am not sure how to add a key or if there is another way to sort the array.
I may be adding more objects to the array later on.
Quick reference to another great answer for this question:
How to sort NSMutableArray using sortedArrayUsingDescriptors?
NSSortDescriptors can be your best friend in these situations :)
What you have done here is create a list with two elements: [NSNumber numberWithInteger:myValue01] and #"valueLabel01". It seems to me that you wanted to keep records, each with a number and a string? You should first make a class that will contain the number and the string, and then think about sorting.
Doesn't the sortedArrayUsingComparator: method work for you? Something like:
- (NSArray *)sortedArray {
return [results sortedArrayUsingComparator:(NSComparator)^(id obj1, id obj2)
{
NSNumber *number1 = [obj1 objectAtIndex:0];
NSNumber *number2 = [obj2 objectAtIndex:0];
return [number1 compare:number2]; }];
}
I am trying to sort an array of managed objects alphabetically. The attribue that they need to be sorted by is the name of the object (NSString) with is one of the managed attributes. Currently I am putting all of the names in an array of strings and then using sortedNameArray = [sortedNameArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)]; and then enumerating them back into an array with the objects. This falls apart when two names are the same so I really need to be able to sort by one attribute. How should I go about doing this?
Use NSSortDescriptor. Just search the documentation on it and there some very simple examples you can copy right over. Here is a simplified example:
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:#"MyStringVariableName" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:valueDescriptor];
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:descriptors];
And just like that you have a sorted array.
You can do this by using NSSortDescriptor,
eg.
`NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc]initWithKey:#"distance" ascending:YES];`
// Here I am sorting on behalf of distance. You should write your own key.
NSArray * descriptors = [NSArray arrayWithObject:valueDescriptor];
NSArray *sortedArray=[yourArray sortedArrayUsingDescriptors:descriptors];`
I am facing a very regular scenario.
I have an NSArray which has object of a custom type, say Person. The Person class has the attributes: firstName, lastName and age.
How can I get an NSArray containing only one attribute from the NSArray having Person objects?
Something like:
NSArray *people;
NSArray *firstNames = [people getArrayOfAttribute:#"firstName" andType:Person.Class]
I have a solution of writing a for loop and fill in the firstNames array but I don't want to do that.
NSArray will handle this for you using KVC
NSArray *people ...;
NSArray *firstName = [people valueForKey:#"firstName"];
This will give you an array of the firstName values from each entry in the array
Check out the filterUsingPredicate: method in NSMutableArray, basically you create a NSPredicate object that will define how the array will be filtered.
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/Predicates/Articles/pUsing.html#//apple_ref/doc/uid/TP40001794-CJBDBHCB
This guide will give you an overview, and has a section for dealing with arrays.
You can also use block based enumeration:
NSArray *people; // assumably has a bunch of people
NSMutableArray *firstNames = [NSMutableArray array];
[people enumerateObjectsUsingBlock:
^(id obj, NSUInteger idx, BOOL*flag){
// filter however you want...
[firstNames addObject:[Person firstName]];
}];
The benefit is it is fast and efficient if you have a bunch of people...
OK, this is a bit obscure, but it's giving me a headache.
If you have an array of strings
{#"1", #"2", #"4"}
And you have a array of Recipe objects
{ {recipe_name:#"Lasagna", recipe_id:#"1"}
{recipe_name:#"Burger", recipe_id:#"2"}
{recipe_name:#"Pasta", recipe_id:#"3"}
{recipe_name:#"Roast Chicken", recipe_id:#"4"}
{recipe_name:#"Sauerkraut", recipe_id:#"5"}
}
How would I, using the first array, create an array like this:
{#"Lasagna", #"Burger", #"Roast Chicken"}
In ither words, it is taking the numbers in the first array and creating an array of recipe_names where the recipe_id matches the numbers...
Use an NSPredicate to specify the type of objects you want, then use -[NSArray filteredArrayUsingPredicate:] to select precisely those objects:
NSArray *recipeArray = /* array of recipe objects keyed by "recipe_id" strings */;
NSArray *keyArray = /* array of string "recipe_id" keys */;
NSPredicate *pred = [NSPredicate predicateWithFormat:#"recipe_id IN %#", keyArray];
NSArray *results = [recipeArray filteredArrayUsingPredicate:pred];
NSPredicate uses its own mini-language to build a predicate from a format. The format grammar is documented in the "Predicate Programming Guide."
If you are targeting iOS 4.0+, a more flexible alternative is to use -[NSArray indexesOfObjectsPassingTest:]:
NSIndexSet *indexes = [recipeArray indexesOfObjectsPassingTest:
^BOOL (id el, NSUInteger i, BOOL *stop) {
NSString *recipeID = [(Recipe *)el recipe_id];
return [keyArray containsObject:recipeID];
}];
NSArray *results = [recipeArray objectsAtIndexes:indexes];
Your array of recipe objects is basically a dictionary:
NSDictionary *recipeDict =
[NSDictionary dictionaryWithObjects:[recipes valueForKey:#"recipe_name"]
forKeys:[recipes valueForKey:#"recipe_id"]];
And on a dictionary you can use the Key-Value Coding method:
NSArray *result = [[recipeDict dictionaryWithValuesForKeys:recipeIDs] allValues];
Assuming that your Recipe objects are key-value compliant (which they almost always are) you can use a predicate like so:
NSArray *recipes= // array of Recipe objects
NSArray *recipeIDs=[NSArray arrayWithObjects:#"1",#"2",#"3",nil];
NSPredicate *pred=[NSPredicate predicateWithFormat:#"recipe_id IN %#", recipeIDs];
NSArray *filterdRecipes=[recipes filteredArrayUsingPredicate:pred];
NSArray *recipeNames=[filterdRecipes valueForKey:#"recipe_name"];
I'm having troubles with arrays and keys... I have an array from my database:
NSArray *elementArray = [[[menuArray valueForKey:#"meals"] valueForKey:#"recipe"] valueForKey:#"elements"]
The problem here is that I would like all my elements of all my meals of all my menus in an array such that:
[elementArray objectAtIndex:0] = my first element
etc...
In the example above, the elements are separated by the keys.
How can I get that?
Hope it's clear enough...
Thanks
From your code snippet, it is not clear to me exactly how your data is structured, but I think it's analogous to having an NSDictionary (called aDictionary) of NSArray and wanting to combine all the NSArray into one. If this is the case, then:
NSMutableArray *resultArray = [[[NSMutableArray alloc] init] autorelease];
for (id dictionaryKey in aDictionary) {
[resultArray addObjectsFromArray:[aDictionary objectForKey:dictionaryKey]];
}
return [NSArray arrayWithArray:resultArray];
(This code has not been tested.)