Filter a NSMutableArray index beyond bounds Problem - iphone

I am trying to filter a NSMutableArray. Search array for items by certain country. I have tried NSpredicate which works great however I need to re-use the original array which I cannot with NSpredicate. So I am trying the below code.
Q. What is the best way to filter an NSMutableArray keeping the original array intact?
//The following code works
filteredArray = [[NSMutableArray alloc] init];
unsigned int i;
for (i = 0; i < [appDelegate.arrayToBeFiltered count]; i++) {
id session = [appDelegate.ads objectAtIndex: i];
id Country = [[appDelegate.arrayToBeFiltered objectAtIndex: i] TheCountry];
[filteredArray addObject: session];
However when I add the if statement as below I get index beyond bounds
filteredArray = [[NSMutableArray alloc] init];
unsigned int i;
for (i = 0; i < [appDelegate.arrayToBeFiltered count]; i++) {
id session = [appDelegate.ads objectAtIndex: i];
id Country = [[appDelegate.arrayToBeFiltered objectAtIndex: i] TheCountry];
if (Country == #"United States"){
[filteredArray addObject: session];
}
}

Use - (NSArray *)filteredArrayUsingPredicate:(NSPredicate *)predicate
As a side-note, in the code above you probably mean to do this [Country isEqualToString: #"United States"]
As an extra side note - don't capitalise variables and method names. Just a style thing but capitalisation is usually reserved for Class names

Related

IOS need to sort an array of dictionaries value based on key price

'm facing problem to sort the values based on key using dictionary object. Actually what i am storing is, each dictionary object having different data type in that dictionary all the data type taking as a string how to convert this string type to specific data type and sort it price vise, my code and out put is bellow, Please help me on this one.
-(IBAction)PriceSort:(id)sender
{
NSSortDescriptor * sort = [[NSSortDescriptor alloc] initWithKey:#"Price" ascending:true] ;
NSArray *sa = [symbolArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:sort]];
NSLog(#"price=%#",sa);
}
out put
{
volume = 2496752;
Yield = "10.49";
MarCap = 829;
Price = "0.715";
Symbol = SAIPI;
},
sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"price"
ascending:YES selector:#selector(localizedStandardCompare:)] ;
Please replace this one and try , hope its works .
-(void)sort
{
//This is the array of dictionaries, where each dictionary holds a record
NSMutableArray * array;
//allocate the memory to the mutable array and add the records to the arrat
// I have used simple bubble sort you can use any other algorithm that suites you
//bubble sort
//
for(int i = 0; i < [array count]; i++)
{
for(int j = i+1; j < [array count]; j++)
{
NSDictionary *recordOne = [array objectAtIndex:i];
NSDictionary *recordTwo = [array objectAtIndex:j];
if([[recordOne valueForKey:#"price"] floatValue] > [[recordTwo valueForKey:#"remaining"] floatValue])
{
[array exchangeObjectAtIndex:i withObjectAtIndex:j];
}
}
}
//Here you get the sorted array
}
Hope this helps.

Converting table view to have sections

I have a table view, which has its data source from an array that contains names of people.
Now to make it easy to find people, I want to section the table view so that it has the letter A-Z on the right hand side, just like the Address Book app.
But my current array just contains a collection of NSStrings. How do I split them so that they are grouped by the first letter of the names? Is there any convenient way to do it?
EDIT: If anyone's interested in my final code:
NSMutableArray *arrayChars = [[NSMutableArray alloc] init];
for (char i = 'A'; i <= 'Z' ; i++) {
NSMutableDictionary *characterDict = [[NSMutableDictionary alloc]init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (int k = 0; k < [myList count]; k++) {
NSString *currentName = [[friends objectAtIndex:k] objectForKey:#"name"];
char heading = [currentName characterAtIndex:0];
heading = toupper(heading);
if (heading == i) {
[tempArray addObject:[friends objectAtIndex:k]];
}
}
[characterDict setObject:tempArray forKey:#"rowValues"];
[characterDict setObject:[NSString stringWithFormat:#"%c",i] forKey:#"headerTitle"];
[arrayChars addObject:characterDict];
[characterDict release];
[tempArray release];
}
At the end of the function I'll have:
arrayChars [0] = dictionary(headerTitle = 'A', rowValues = {"adam", "alice", etc})
arrayChars[1] = dictionary(headerTitle = 'B', rowValues = {"Bob", etc})
Thank you everyone for your help!
You can use a dictionary to sort them, so create an array with all the letters you want to sort and a array with nil objects to initialize the dictionary
NSArray *names = #[#"javier",#"juan", #"pedro", #"juan", #"diego"];
NSArray *letters = #[#"j", #"p", #"d"];
NSMutableArray *objects = [[NSMutableArray alloc] init];
for (NSInteger i = 0; i < [letters count]; ++i)
{
[objects addObject:[[NSMutableArray alloc] init]];
}
NSDictionary *dictionary = [[NSDictionary alloc] initWithObjects:objects forKeys:letters];
Then you must find the first letter if the word and put that word into the corresponding key in the dictionary
for (NSString *name in names) {
NSString *firstLetter = [name substringToIndex:1];
for (NSString *letter in letters) {
if ([firstLetter isEqualToString:letter]) {
NSMutableArray *currentObjects = [dictionary objectForKey:letter];
[currentObjects addObject:name];
}
}
}
To check you can print directly the dictionary
NSLog(#"%#", dictionary);
Then is your work to fill your sections in the tableview using the dictionary

Problem adding custom objects to Mutable Array

quick question regarding Array's in xcode. I have ht efollowing code, which is supposed to go through an array of strings which it has got through php and JSON, and trun these strings into a custom object with the strings as the ivars for the object then add that object to a new array:
for (int i = 0; i<[list count]; i++) {
Article *article = [[Article alloc] init]; //creates custom object
article.uid = [[list objectAtIndex:i] objectAtIndex:0];
article.title = [[list objectAtIndex:i] objectAtIndex:1]; //adds string as ivars
article.description = [[list objectAtIndex:i] objectAtIndex:2];
articleArray = [[NSMutableArray alloc] init]; //inits the new array
[articleArray addObject:article]; //should add the object but seems to fail
[article release]; //releases the object
NSLog(#"%#", article.description);
}
NSLog(#"%d", [articleArray count]);
NSLog([articleArray description]);
}
The code does return the correct values using NSLog(#"%#", article.description); but not the correct length for the new array and it only adds one value to the array which is the string for article.description which makes no sense to me. The list array contains 2 elements each of which are arrays in themselves containing the strings.
You're recreating the articleArray in every loop. Declarate it outside, and it will work:
NSMutableArray *articleArray = [[NSMutableArray alloc] init]; //inits the new array
for (int i = 0; i<[list count]; i++) {
Article *article = [[Article alloc] init]; //creates custom object
article.uid = [[list objectAtIndex:i] objectAtIndex:0];
article.title = [[list objectAtIndex:i] objectAtIndex:1]; //adds string as ivars
article.description = [[list objectAtIndex:i] objectAtIndex:2];
[articleArray addObject:article]; //should add the object but seems to fail
[article release]; //releases the object
NSLog(#"%#", article.description);
}
NSLog(#"%d", [articleArray count]);
NSLog([articleArray description]);
}
You also may want to use the nicer for(NSArray *listElement in list) syntax instead.

Adding # & search sign to TableIndex in UITableView

In iPhone native Phone book - there is a search character at the top & # character at the bottom.
I want to add both of that character in my table Index.
Currently I have implemented following code.
atoz=[[NSMutableArray alloc] init];
for(int i=0;i<26;i++){
[atoz addObject:[NSString stringWithFormat:#"%c",i+65]];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView{
return atoz;
}
How to have # character & search symbol in my UITableView?
The best way to tackle this is to make use of the tools the framework provides. In this case, you want to use UILocalizedIndexedCollation (developer link).
I also have a decorator for this class that is designed to insert the {{search}} icon for you and handle the offsets. It is a like-for-like drop-in replacement for UILocalizedIndexedCollation.
I've posted a more in-depth description of how to use this on my blog. The decorator is available here (Gist).
The basic idea is to group your collection into an array of arrays, with each array representing a section. You can use UILocalizedIndexedCollation (or my replacement) to do this. Here's a small NSArray category method I use to do this:
#implementation NSArray (Indexing)
- (NSArray *)indexUsingCollation:(UILocalizedIndexedCollation *)collation withSelector:(SEL)selector;
{
NSMutableArray *indexedCollection;
NSInteger index, sectionTitlesCount = [[collation sectionTitles] count];
indexedCollection = [[NSMutableArray alloc] initWithCapacity:sectionTitlesCount];
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *array = [[NSMutableArray alloc] init];
[indexedCollection addObject:array];
[array release];
}
// Segregate the data into the appropriate section
for (id object in self) {
NSInteger sectionNumber = [collation sectionForObject:object collationStringSelector:selector];
[[indexedCollection objectAtIndex:sectionNumber] addObject:object];
}
// Now that all the data's in place, each section array needs to be sorted.
for (index = 0; index < sectionTitlesCount; index++) {
NSMutableArray *arrayForSection = [indexedCollection objectAtIndex:index];
NSArray *sortedArray = [collation sortedArrayFromArray:arrayForSection collationStringSelector:selector];
[indexedCollection replaceObjectAtIndex:index withObject:sortedArray];
}
NSArray *immutableCollection = [indexedCollection copy];
[indexedCollection release];
return [immutableCollection autorelease];
}
#end
So, given an array of objects, for example books that I want to divide into sections based on their name (the Book class has a name method), I would do this:
NSArray *books = [self getBooks]; // etc...
UILocalizedIndexedCollation *collation = [UILocalizedIndexedCollation currentCollation];
NSArray *indexedBooks = [books indexUsingCollation:collation withSelector:#selector(name)];

NSArray to NSMutableArray as random stack

Just a conceptual description first:
I am reading input from a text file (a list of words) and putting these words into an NSArray using componentsSeparatedByString method. This works.
But I wanted to select the words randomly and then delete them from the array so as to ensure a different word each time. Of course, you cannot change the NSArray contents. So...
I copied the contents of the NSArray into an NSMutableArray and use IT for the selection source. This also works - 269 objects in each array.
To return a word from the NSMutableArray I use the following code:
note- the arrays are declared globally
as
arrMutTextWords = [[NSMutableArray alloc] init]; //stack for words
arrTextWords = [[NSArray alloc] init]; //permanent store for words
-(NSString*) getaTextWord
{
// if the mutable text word array is empty refill
if ([arrMutTextWords count] == 0){
for (int i = 0 ; i < [arrTextWords count]; i++)
[arrMutTextWords addObject:[arrTextWords objectAtIndex:i]];
}
int i = random() % [arrMutTextWords count];
NSString* ptrWord = [arrMutTextWords objectAtIndex:i];
[arrMutTextWords removeObjectAtIndex:i];
return ptrWord;
}
The program crashes during a call to the method above - here is the calling code:
arrTmp is declared globally arrTmp = [[NSArray alloc] init]; //tmp store for words
for (int i = 0 ; i < 4; i++) {
tmpWord = [self getaTextWord];
[arrTmp addObject:tmpWord];
[arrTmp addObject:tmpWord];
}
I'm thinking that somehow deleting strings from arrMutTextWords is invalidating the NSArray - but I can't think how this would occur.
One possible source for problems is your fetching AND removing the NSString object from your list. Removing it releases that NSString instance therefore devalidating your reference.
To be shure to retain a reference you should use this code sequence instead:
NSString * ptrWord = [[[arrMutTextWords objectAtIndex:i] retain] autorelease];
[arrMutTextWords removeObjectAtIndex:i];
return ptrWord;
By the way: You should use
NSMutableArray *mutableArray = [NSMutableArray arrayWithArray: array];
instead of copying all values by hand. While i do not know the implementation of NSMutableArray, i know from times long ago (NeXTstep), that there are several possible optimizations that may speed up basic NSArray operations.
And finally copying this way is much more concise.
Just ran this through XCode and got random words returned, however I skipped the whole for loop and used addObjectsFromArrayfrom NSMutableArray.
NSArray *randomArray = [[NSArray alloc] initWithObjects:#"Paul", #"George", #"John", nil];
NSMutableArray *muteArray = [[NSMutableArray alloc] init];
[muteArray addObjectsFromArray:randomArray];
int i = random() % [muteArray count];
NSString* ptrWord = [muteArray objectAtIndex:i];
[muteArray removeObjectAtIndex:i];
NSLog(#"ptrWord %#", ptrWord); //gave me a different name each time I ran the function.
Hope this clears some things up.