Create 1 million NSMutableArrays with unique names easily - iphone

After teaching myself (mostly from this website) I have finally been unable to find a solution to a problem.
I am trying to easily create 1 million NSMutableArrays with unique names. What I mean by easily is not having 'hard code' all of the individual arrays.
What I would like to do is something like this:
for (int i = 1; i <= 1000000; i++) {
NSString *arrayNumber = [NSString stringWithFormat:#"%d", i];
NSString *millionArrayNumber = #"millionArrayNumber";
NSString *arrayName = [millionArrayNumber stringByAppendingString:arrayNumber];
NSMutableArray *[NSString arrayName] = [NSMutableArray array];
}
I can understand why this doesn't work but I can't think of another way of doing it. I thought it might be possible to use something similar to:
[button setTag = 1];
If I change the code to:
for (int i = 1; i <= 1000000; i++) {
NSMutableArray *millionArray = [NSMutableArray array];
[millionArray setTag: i];
}
I would then use the tag to control the arrays as you can do with buttons. This doesn't work for arrays though.
I hope I haven't been ambiguous.

I'm not sure how to convert a string into literal code like you're doing, but I think it's possible.
However, you can always just kick 1 million arrays to an NSMutableDictionary and give each one your unique key name.
NSMutableDictionary *arrayStore = [NSMutableDictionary dictionary];
for (int i = 1; i <= 1000000; i++) {
NSString *arrayNumber = [NSString stringWithFormat:#"%d", i];
NSString *millionArrayNumber = #"millionArrayNumber";
NSString *arrayName = [millionArrayNumber stringByAppendingString:arrayNumber];
arrayStore[arrayName] = [NSMutableArray array];
}
And obviously to get whatever array you want later, you just use:
NSMutableArray *uniqueArray = arrayStore[arrayName];
Edit: Not sure if you want to keep the number as the unique key as mentioned in the comment below but if so, you can do it with this:
NSMutableDictionary *arrayStore = [NSMutableDictionary dictionary];
for (int i = 1; i <= 1000000; i++) {
arrayStore[#(i)] = [NSMutableArray array];
}
And access it with (for example, array number 100):
NSMutableArray *uniqueArray = arrayStore[#100];

Related

Initialize an NSArray with the numbers in a sequential manner when the count of the array is known

I want to initialize an NSArray with numbers starting from 0,1,2,3... I know the count of the array. For example:
I have an array that needs to be initialized with 5 (count) as capacity. Now I want to initialize this array with 0,1,2,3,4 and I need to initialize it dynamically.
If the count of the array is 10, I need to initialize the array with 0,1,2,3,4,5,6,7,8,9 at respective indexes. The problem is that count of the array changes dynamically and I need to initialize it accordingly.
Can someone suggest me any idea on how to implement this?
NSMutableArray* arrOfObject = [[NSMutableArray alloc] init];
for(int i=0; i< [arr count]; i++)
{
arrOfObject addObject:[NSNumber numberWithInt:i];
}
Initialize a mutable array. Then add the numbers in a loop. Optionally initialize a new non-mutable array with your mutable one using arrayWithArray:.
int count = 5;//suppose this you want
NSMutableArray *array = [NSMutableArray array];
for(int i=0 ; i< count; i++) {
[array addObject:[NSNumber numberWithInt:i];
}
You just need to pass the count from where you want it, and it will dynamically generate your desired array.
Use NSMutableArray then just add as many as you need
int count = 10;
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i=0;i<count;i++) {
[array addObject:[NSNumber numberWithInt:i]];
}

Fastest way to compare/set strings

I have an array of Place objects. Each Place object has a name and code property, both strings. Each Place object already has a code, but I need to look up the name property from a server. I get back 2 arrays: one contains name, the other codes. These arrays are ordered so that the name at some index in the nameArray corresponds exactly with the code at the same index of the codeArray.
I have been looping through the array of Place objects, then checking to see if the code property for that Place is the same as the current index in the codeArray. If it is, I set the name of that Place by using the same index in the nameArray:
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [codeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[codeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
}
}
}
This works but isn't terribly fast - it can take 30 seconds with 1000+ Places to loop through.
Is there a faster way?
As with anytime you're trying to optimize performance, you should profile the code using Instruments to find out where the bottleneck actually is. That said, looping through the placesArray for each name in the nameArray and doing a string comparison is pretty inefficient.
How about something like this?
NSMutableDictionary *placesByCode = [NSMutableDictionary dictionaryWithCapacity:[placesArray count]];
for (Place *aPlace in placesArray) {
[dictionary setObject:aPlace forKey:aPlace.code];
}
NSMutableDictionary *namesByCode = [NSMutableDictionary dictionaryWithCapacity:[namesArray count]];
for (int i=0; i<[namesArray count]; i++) {
NSString *name = [namesArray objectAtIndex:i];
NSString *code = [codeArray objectAtIndex:i];
[namesByCode setObject:name forKey:code];
}
for (NSString *code in namesByCode) {
Place *place = [placesByCode objectForKey:code];
place.name = [namesByCode objectForKey:namesByCode];
}
Looking up each place by its code in the dictionary should be quite a bit faster than manually looping through the whole place array for each name.
You can use for NSArray -containsObject
if ([myarray containsObject:myObject]) {
// ...
}
Try using a break statement in the inner loop. This way you don't need to loop through the entire loop each time.
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [codeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[codeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
break;
}
}
}
You could also make the second array become smaller as you find more results. It will cost you more memory but 1000 strings isn't much anyway.
NSMutableArray * tempCodeArray = [NSMutableArray arrayWithArray:codeArray];
for(int i = 0; i < [placesArray count]; i++)
{
for(int j = 0; j < [tempCodeArray count]; j++) {
if([[[placesArray objectAtIndex:i] code] isEqualToString:[tempCodeArray objectAtIndex:j]]) {
[[placesArray objectAtIndex:i] setName:[nameArray objectAtIndex:j]];
[tempCodeArray removeObjectAtIndex:j];
break;
}
}
}
The problem was not the counting for the array, it's the embedded for loop which will take O(n*n) and in Andrew's solution, it's only O(n)+O(n)+O(n)+whatever take to find a object of the key in the dictionary, which i guess would be in a hash table lookup and that's really fast.
Colby, you probably will be ok with Andrew's solution. If you still wanna improve the performance, then a good idea would be sort the array's first then do lookup.
Hope this helps.

Loading values into an array from two different arrays iphone sdk

Here I am having a situation, I'm using the following code:
int x=0;
for (int i=0; i<=[arrayDeals count]-1; i++) {
x++;
//NSString *deal = [arrayDeals objectAtIndex:i];
combinedArr = [[NSMutableArray alloc]initWithObjects:
[CustomObject customObjectWithName:[arrayDeals objectAtIndex:i] andNumber:x],nil];
}
I need to load the values from arrayDeals and the 'x' value into combinedArr. So, I put this in a for loop. But i got only one value from each arrays. What is went wrong here? Please help me. (here CustomObject is a NSObject)
Thank you.
Well there are many things wrong with the code you posted, but I think this is what you want:
int x = 0;
NSMutableArray *combinedArr = [[NSMutableArray alloc] init]:
NSInteger count = [arrayDeals count];
for (int i = 0; i < count; i++) {
x++;
CustomObject *customObject = [CustomObject customObjectWithName:[arrayDeals objectAtIndex:i] andNumber:x];
[combinedArr addObject:customObject];
}
To give you some idea of what is wrong with the code you posted:
combinedArr = [[NSMutableArray alloc]initWithObjects:
[CustomObject customObjectWithName:[arrayDeals objectAtIndex:i] andNumber:x],nil];
Here you create a new NSMutableArray to which you assign an new object to taked the object from the array arrayDeals. But you create this NSMutableArray for every item in the array arrayDeals and you assign them to the same variable.
So each iteration you leak the NSMutableArray.
Also :
for (int i=0; i<=[arrayDeals count]-1; i++) {
is the same as
for (int i=0; i < [arrayDeals count]; i++) {
but the count is called every time you iterate, so as per my example I saved the count in a int to just speed things up.
You could even speed the code up using fast Enumeration:
NSInteger x = 0;
NSMutableArray *combinedArr = [[NSMutableArray alloc] init]:
for (id object in arrayDeals) {
id secondObject = [secondArray itemAtIndex:x];
// Arrays start at 0 so only up it after we've got the object.
x++;
CustomObject *customObject = [CustomObject customObjectWithName:object andNumber:x];
[combinedArr addObject:customObject];
}

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.

Filter a NSMutableArray index beyond bounds Problem

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