Populating array with integers - objective-c

Let's say I want to populate NSarray with 50 integers. We know that NSarray accept only objects. So I have to do 50 times
NSNumber *num1 = [NSNumber numberWithInit:10];
NSNumber *num2 = [NSNumber numberWithInit:212];
......
NSNumber *num50 = [NSNumber numberWithInit:12];
Is there more elegant way to achieve that, beacause looks stupid 50 lines of code only for create number objects ?

try this...
NSMutableArray *array=[[NSMutableArray alloc]initWithCapacity:50 ];
for (int i=0; i<0; i++) {
NSNumber *number=[[NSNumber alloc] initWithInt:i];
[array addObject:number];
[number release];
}
//do anything with arrray and release the array later.
is this OK or you are seeking anything else.?

How about using NSMutableArray?
NSMutableArray* arr = [[NSMutableArray alloc] init];
int i = 0;
for(i=0; i<50; i++) {
NSNumber* num = [NSNumber numberWithInt:i]; // use i or random numbers
[arr addObject:num];
}

Your numbers do not seem to follow any particular pattern, so you might be better doing this by creating a C array first:
int myValues[] = { 10, 212, ..., 12 };
NSUInteger count = sizeof(myValues)/sizeof(int); // number of integers in myValues
// abstract the following into a function/method/category if doing more than once
NSMutableArray *objcValues = [NSMutableArray arrayWithCapacity:count];
for(NSUInteger ix = 0; ix < count; ix++)
[objcValues addObject:[NSNumber numberWithInt:myValues[ix]];

Related

Objective C - Array With Numbers

Is there a nicer way to fill an array with numbers than what I use?
It's crazy how much I got to write just to fill an array with numbers so they can be used for a calculation in a loop. This is easier in other C based languages like PHP, As3, or Java.
NSArray *myArray = [NSArray arrayWithObjects:
[NSNumber numberWithInt:1000],[NSNumber numberWithInt:237], [NSNumber numberWithInt:2673], nil];
int total = 0;
for(int i = 0; i < [myArray count]; i += 1 ){
total += [[myArray objectAtIndex: i]intValue];
NSLog(#"%i", total);
}
Hopefully there is a shorter way... I just want to fill an array with ints... cant be that hard
I guess you have to use NSNumber for an NSArray. If you want to use ints I guess you'd have to use a c array:
NSInteger myArray[20];
for (int i=0;i<20;i++) {
int num=myArray[i];
//do something
}
NSNumber though is I guess the better approach for this language.
At least you can do fast enumeration to shorten code a bit:
for (NSNumber *n in myArray) {
int num = [n intValue];
//do something....
}
EDIT:
The question has been asked 3 years ago. There have been new literals established to make it easier to create objects like NSNumbers or NSArrays:
NSNumber *n = #100;
or
NSArray *array = #[#100,#50,#10];
Nice short alternative for looping specific integers:
NSArray *numbers = [#"1000,237,2673" componentsSeparatedByString:#","];
for (NSString *i in numbers) {
[i intValue]; // Do something.
}
First start with a C array:
NSInteger myCArray = { 1000, 237, 2673 };
// calculate number of elements
NSUInteger myCArrayLength = sizeof(myCArray) / sizeof(NSInteger;
Second, if you need an NSArray loop through this array and create one:
NSMutableArray *myNSArray = [NSMutableArray arrayWithCapacity:myCArrayLength];
for(NSUInteger ix = 0; ix < myCArrayLength; ix++)
[myNSArray addObject:[NSNumber numberWithInteger:myCArray[ix]];
You can wrap the second piece of code up as a category on NSArray if you're doing it a lot.
too late. but u can do the following too.
int total = 0;
nsarray *myArray = #[#1.8,#100,#299.8];
for(nsnumber *num in myArray){
total+=num;
}

Reading random values from an array

I have an array with a 14 strings. I want to display each of these 14 strings to the user without duplicates. The closest I got was creating an array of integers and shuffling their values, and then reading from the array of strings using one of the numbers from the int array as the index:
//appDelegate.randomRiddles is an array of integers that has integer values randomly
appDelegate.randomRiddlesCounter++;
NSNumber *index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
int i = [index intValue];
while(i>[appDelegate.currentRiddlesContent count]){
appDelegate.randomRiddlesCounter++;
index=[appDelegate.randomRiddles objectAtIndex:appDelegate.randomRiddlesCounter];
i = [index intValue];
}
hintText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"hint"];
questionText.text = [[appDelegate.currentRiddlesContent objectAtIndex:i] objectForKey:#"question"];
But my way is causing crashing and duplicates. Oh and each time I read a value from the strings array, that string is removed from the array making its count decrease by 1. So that complicates this a little bit.
Get the elements in your array like this:
int position = arc4random() % ([myArray count]);
This way even though count decreases by one, that is ok, as you will still get a valid next position value till there aren't any more posible values.
By "without duplicates" I assume you mean that you want to use each string in the array once before you use the same string again, not that you want to filter the array so it doesn't contain duplicate strings.
Here's a function that uses a Fisher-Yates shuffle:
/** #brief Takes an array and produces a shuffled array.
*
* The new array will contain retained references to
* the objects in the original array
*
* #param original The array containing the objects to shuffle.
* #return A new, autoreleased array with all of the objects of
* the original array but in a random order.
*/
NSArray *shuffledArrayFromArray(NSArray *original) {
NSMutableArray *shuffled = [NSMutableArray array];
NSUInteger count = [original count];
if (count > 0) {
[shuffled addObject:[original objectAtIndex:0]];
NSUInteger j;
for (NSUInteger i = 1; i < count; ++i) {
j = arc4random() % i; // simple but may have a modulo bias
[shuffled addObject:[shuffled objectAtIndex:j]];
[shuffled replaceObjectAtIndex:j
withObject:[original objectAtIndex:i]];
}
}
return shuffled; // still autoreleased
}
If you want to keep the relationship between the riddles, hints, and questions then I'd recommend using a NSDictionary to store each set of related strings rather than storing them in separate arrays.
This task is very easy using an NSMutableArray. In order to do this, simply remove a random element from the array, display it to the user.
Declare a mutable array as an instance variable
NSMutableArray * questions;
When the app launches, populate with values from myArray
questions = [[NSMutableArray alloc] initWithArray:myArray]];
Then, to get a random element from the array and remove it, do this:
int randomIndex = (arc4random() % [questions count]);
NSDictionary * anObj = [[[questions objectAtIndex:randomIndex] retain] autorelease];
[questions removeObjectAtIndex:randomIndex];
// do something with element
hintText.text = [anObj objectForKey:#"hint"];
questionText.text = [anObj objectForKey:#"question"];
No need to type that much. To shuffle an array, you just sort it with random comparator:
#include <stdlib.h>
NSInteger shuffleCmp(id a, id b, void* c)
{
return (arc4random() & 1) ? NSOrderedAscending : NSOrderedDescending;
}
NSArray* shuffled = [original sortedArrayUsingFunction:shuffleCmp context:0];
You could copy the array into an NSMutableArray and shuffle that. A simple demonstration of how to shuffle an array:
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// Original array, here initialised with 1..9
NSArray *arr = [NSArray arrayWithObjects:
[NSNumber numberWithInt: 1],
[NSNumber numberWithInt: 2],
[NSNumber numberWithInt: 3],
[NSNumber numberWithInt: 4],
[NSNumber numberWithInt: 5],
[NSNumber numberWithInt: 6],
[NSNumber numberWithInt: 7],
[NSNumber numberWithInt: 8],
[NSNumber numberWithInt: 9],
nil];
// Array that will be shuffled
NSMutableArray *shuffled = [NSMutableArray arrayWithArray: arr];
// Shuffle array
for (NSUInteger i = shuffled.count - 1; i > 0; i--)
{
NSUInteger index = rand() % i;
NSNumber *temp = [shuffled objectAtIndex: index];
[shuffled removeObjectAtIndex: index];
NSNumber *top = [shuffled lastObject];
[shuffled removeLastObject];
[shuffled insertObject: top atIndex: index];
[shuffled addObject: temp];
}
// Display shuffled array
for (NSNumber *num in shuffled)
{
NSLog(#"%#", num);
}
[pool drain];
return 0;
}
Note that all arrays and numbers here are autoreleased, but in your code you might have to take care of memory management.
If you don't have to keep the elements in the array, you can simplify that (see Oscar Gomez' answer too):
NSUInteger index = rand() % shuffled.count;
NSLog(#"%#", [shuffled objectAtIndex: index]);
[shuffled removeObjectAtIndex: index];
At the end, shuffled will be empty. You will have to change the loop conditions too:
for (NSUInteger i = 0; i < shuffled.count; i++)

How to simplify my code... 2D NSArray in Objective C...?

self.myArray = [NSArray arrayWithObjects: [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil], [NSArray arrayWithObjects: [self generateMySecretObject], [self generateMySecretObject],nil],nil];
for (int k=0; k<[self.myArray count]; k++) {
for(int s = 0; s<[[self.myArray objectAtIndex:k] count]; s++){
[[[self.myArray objectAtIndex:k] objectAtIndex:s] setAttribute:[self generateSecertAttribute]];
}
}
As you can see this is a simple 2*2 array, but it takes me lots of code to assign the NSArray in very first place, because I found that the NSArray can't assign the size at very beginning. Also, I want to set attribute one by one. I can't think of if my array change to 10*10. How long it could be. So, I hope you guys can give me some suggestions on shorten the code, and more readable. thz
(Some Assumptions: myArray will have a fixed size. It won't grown up or become smaller in the run time.)
Generate the array by -addObject:.
NSMutableArray* myArray = [NSMutableArray array];
for (int k = 0; k < 10; ++ k) {
NSMutableArray* subArr = [NSMutableArray array];
for (int s = 0; s < 10; ++ s) {
id item = (s == 0 && k == 0) ? [self d] : [self generateMySecretObject];
[item setAttribute:[self generateSecertAttribute]];
[subArr addObject:item];
}
[myArray addObject:subArr];
// use [myArray addObject:[[subArr copy] autorelease]] for deep immutability.
}
return [[myArray copy] autorelease];
(Don't query self.myArray many times. Each corresponds to an ObjC call and while someone calls an ObjC call is cheap, it's still not free.)
If the array is a fixed size and each row is the same length then you could uses a 1D array and an offset, EG:
int rowLength = 5;
int rowNumber = 0;
int columnNumber = 3;
[myArray objectAtIndex: (rowLength * rowNumber) + columnNumber];

Can I assign array size using NSMutableArray?

I used to be a Java Programmer, which the array need to declare the very first time, like this:
int[] anArray; // declares an array of integers
anArray = new int[10]; // allocates memory for 10 integers
I don't know whether the Objective C , NSMutableArray also give me this ability or not. Actually, I want to make a 10*10 array. thz in advance.
I try to do this:
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my incompatible type assignment.
The capacity field is seldom useful. The array will be expanded on demand anyway.
And the capacity field just tells the array how much memory you may use. The array's length is still 0.
But you can grow the array from empty:
for (int i = 0; i < 10; ++ i)
[myArray addObject:…];
To read and write to an element in an NSMutableArray, you need:
id x = [array objectAtIndex:i]; // x = array[i];
[array replaceObjectAtIndex:i withObject:y]; // array[i] = y;
You cannot subscript an NSArray directly.
Your code has memory leak. Unlike Java, ObjC doesn't use a GC unless you explicitly enable it (and ObjC on iPhoneOS doesn't have GC). ObjC manages memory by manual reference counting. Basically you need to ensure the ref count of stuff you don't own doesn't change in the process. See http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html for detail.
In your case, [[NSMutableArray alloc] …]; creates an object of ref count +1, then the assignment will take over the array, that means you don't own it any more, but the ref count is not balanced to 0, so this memory will not be properly deallocated. You need to use convenient methods such as [NSMutableArray array…] to create an object with ref count 0.
NSArray's can only store ObjC objects. int in C (ObjC) is a primitive, and cannot be stored into an NSArray. You have to box it into an NSNumber by [NSNumber numberWithInt:0]. You can get back the integer with -intValue.
To conclude, your code needs to be modified as:
-(NSMutableArray*)get10x10Array {
NSMutableArray* arr = [NSMutableArray array];
for (int i = 0; i < 10; ++ i) {
NSMutableArray* subarr = [NSMutableArray array];
for (int j = 0; j < 10; ++ j)
[subarr addObject:[NSNumber numberWithInt:0]];
[arr addObject:subarr];
}
return arr;
}
But ObjC is a superset of C. You can just use a plain 10x10 C array.
int arr[10][10];
You want a 10x10 array -- of what?
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
myArray[i] = [[NSMutableArray alloc] initWithCapacity:10];
}
But it occurs errors, telling my
incompatible type assignment.
Because you can't assign to myArray like that. myArray is an object that represents an array data structure. It is not a C array.
If you want a 10x10 array of a primitive data type, you can declare one like you would in C:
int myArray[10][10];
initWithCapacity: is what you want. It may look like
NSMutableArrat *array = [[NSMutableArray alloc] initWithCapacity:10];
You can't access Cocoa array objects with the bracket notation. Your second bit of code should be:
NSMutableArray *myArray = [[NSmutableArray alloc] initWithCapacity:10];
for (int i = 0; i < 10; i++) {
[myArray insertObject:[NSMutableArray arrayWithCapacity:10] atIndex:i]; // Note: not using myArray[i]!
}
There are two ways to do this.
Plain old C
If you want to store objects, you should use the id type instead of int.
int myarray[10][10];
myarray[5][2] = 412;
Objective-C
NSArray's are not meant to have spaces without objects, if you need them you could use [NSNull null], but if that's the case a C array would be better anyway.
NSMutableArray *myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i < 10; i++) {
NSMutableArray *innerArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int j=0; j < 10; j++) {
[innerArray addObject:[NSNull null]];
}
[myArray addObject:innerArray];
[innerArray release];
}
[[myArray objectAtIndex:5]
replaceObjectAtIndex:2 withObject:[NSNumber numberWithInteger:123]];
NSArray objects have a fixed size that cannot be changed once they have been initialised. NSMutableArray objects can change size. A 10×10 array is sometimes implemented as an NSArray containing 10 individual NSArray objects, each of these containing ten items. This quickly gets cumbersome, sometimes it is easier to resort back to plain C for such a task:
int tenByTen[10][10];
Or, you can use this:
typedef struct
{
int y[10];
} TenInts;
typedef struct
{
TenInts x[10];
} TenByTen;
Then you could do:
- (void) doSomethingWithTenByTen:(const TenByTen) myMatrix
{
NSLog ("%d", myMatrix.x[1].y[5]);
}
And you can also return them from methods:
- (TenByTen) mangleTenByTen:(const TenByTen) input
{
TenByTen result = input;
result.x[1].y[4] = 10000;
return result;
}
You want NSMutableArray +arrayWithCapacity:
Note that setting the initial capacity is merely an optimization - Mutable arrays expand as needed.
EDIT:
To do the 10x10 case,
myArray = [[NSMutableArray alloc] initWithCapacity:10];
for (int i=0; i<10; i++) {
NSMutableArray *subArray = [NSMutableArray arrayWithCapacity:10];
[myArray addObject:subArray];
for (int j = 0; j<10; j++) {
[subArray addObject:[NSNumber numberWithInt:0]];
}
}
Notes:
an array retains the objects added to it, so its not necessary to retain subArray
only objects (not primitive types like "int") can be added to an NSArray, hence the need for NSNumber numberWithInt:
you use methods like objectAtIndex: and replaceObjectAtIndex:withObject: to get/set a value from an NSArray, not array subscript ([]) syntax
See Apple refs for NSArray and NSMutableArray
You can use the following code to resize the NSMutableArray once it was created:
#interface NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize;
#end
#implementation NSMutableArray (Resizing)
- (NSMutableArray *)resize:(NSInteger)newSize
{
int size = (newSize > [self count]) ? self.count : newSize;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:size];
for (int i = 0; i < size; i++){
[array addObject:[self objectAtIndex:i]];
}
return array;
}
#end

Create multiple numbered variables based on a int

How would I create a number of NSDictionary variables using an array's count?
This is basically what I came up with, but I'm not sure how to make this work with Objective-C syntax. doesntContainAnother is an NSArray. I want the names of the dictionaries to use the current value of loopInt.
int *loopInt = 0;
while (doesntContainAnother.count <= loopInt) {
NSMutableDictionary *[NSString stringWithFormat:#"loopDictionary%i", loopInt] = [[[NSMutableDictionary alloc] init] autorelease];
[NSString stringWithFormat:#"loopDictionary%i", loopInt] = [NSDictionary dictionaryWithObject:[array1 objectAtIndex:loopInt]
forKey:[array2 objectAtIndex:loopInt]];
loopInt = loopInt + 1;
}
Create a mutable array and loop until you reach the original array's count, creating a dictionary and adding it to the mutable array on each iteration.
Your code should look like this.
NSMutableArray *dictionaries = [[NSMutableArray alloc] init];
for (int i = 0; i < doesntContainAnother.count; i++) {
[dictionaries addObject:[NSMutableDictionary dictionaryWithObject:[array1 objectAtIndex:i] forKey:[array2 objectAtIndex:i]]];
}
The approach of creating variables with numbers at the end of their names is an antipattern and not even possible in Objective-C. It's equivalent to an array, but clunkier.
You need to create a mutable array, and then put the objects into the array. You can't create a variable with the same name as the contents of a string, as you have done. For example:
NSMutableArray *arr = [[NSMutableArray alloc] initWithCapacity:[doesntContainAnother count]];
int i = 0; // Note: type is int, not int*
for (i = 0; i < [doesntCountainAnother count]; i++) {
[arr addObject:[NSMutableDictionary dictionary]];
}
// Later...
NSMutableDictionary *d1 = [arr objectAtIndex:3];
Or if you want to pull them out of the list by name:
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithCapacity:[doesntCountainAnother count]];
int i = 0;
for (i = 0; i < [doesntContainAnother count]; i++) {
[dict setObject:[NSMutableDictionary dictionary] forKey:[NSString stringWithFormat:#"loopDictionary%d", i]];
}
// Later...
NSMutableDictionary *d1 = [dict objectForKey:#"loopDictionary3"];
But the first way is likely the easiest.