Getting an NSArray of a single attribute from an NSArray - iphone

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

Related

how to add object at specified index in NSMutable array?

How can I add object at specified index?
in my problem
NSMutableArray *substring
contains index and object alternatively
and I need to add it to the another array str according to index I getting from this array.
NSMutableArray *str=[NSMutableArray new];
if ([substrings containsObject:#"Category-Sequence:"])
{
NSString *index=[substrings objectAtIndex:5];
//[substrings objectAtIndex:5]
gives me integer position at which I need to add object in `str` array,
gives 5,4,8,2,7,1 etc
NSString *object=[substrings objectAtIndex:1];
//[substrings objectAtIndex:1] gives object,gives NSString type of object
[str insertObject:object atIndex:(index.intValue)];
}
please suggest some way to achieve it.
Thanks in advance!
Allocate the array first & then try to add objects in it.
NSMutableArray *str = [[NSMutableArray alloc]init];
if ([substrings containsObject:#"Category-Sequence:"])
{
NSString *index=[substrings objectAtIndex:5];
NSString *object=[substrings objectAtIndex:1];
[str insertObject:object atIndex:(index.intValue)];
}
Allocate the NSMutableArray before inserting objects into it:
NSMutableArray *strMutableArray = [[NSMutableArray alloc] init];
(You’ll also need to release it when you’re done if you’re not using ARC.)
Or you could also use a temporary object, if you don’t need to keep strMutableArray:
NSMutableArray *strMutableArray = [NSMutableArray array];
Then you can insert objects into the NSMutableArray.
Be careful with using indexes of and in different arrays, however. There might be a better way to do what you want.

Sort an NSMutableArray / Dictionary with several objects

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]; }];
}

Create NSArray From Objects in NSMutableArray

I have NSMutableArray with 10,000 objects, each object has Name, Details, ...etc.
I want to Create an NSArray Which contains ONLY the Names of all objects.
Use KVC
NSArray *names = [myArray valueForKey:#"name"];
Check the docs for NSArray
valueForKey:
Returns an array containing the results of invoking valueForKey: using key on each of the array's objects.

Sort array with custom objects

I'm trying to sort an array, filled with objects from a class i wrote. The class i wrote contains an NSString itself, as the "name". So what i wanna do, is to sort the array, based on the name property the objects contain. I tried the simple:
[anArray sortedArrayUsingSelecter: CaseInsensitiveCompare];
But as you can guess, it sends the caseInsensitiveCompare message to the objects itself, and it won't respond to that one.
So i'm guessing i have to make my objects able to respond to the caseInsensitiveCompare? Not quite sure how to write such a method, so any pointers would be lovely.
Thanks
You can use the method sortedArrayUsingComparator:
NSArray *sortedArray = [anArray sortedArrayUsingComparator:^(MyClass *a, MyClass *b) {
return [a.name caseInsensitiveCompare:b.name];
}];
You can sortedArrayUsingComparator:(NSComparator)cmptr (NSArray reference) to sort the array. For instance, if you want to sort by the name property, do the following (assuming your class is called Person):
NSArray *sortedArray = [anArray sortedArrayUsingComparator:^(id a, id b) {
NSString *first = [(Person *)a name];
NSString *second = [(Person *)b name];
return [first caseInsensitiveCompare:second];
}];

Extracting strings from a NSArray of objects, based on a array of NSStrings

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"];