How to save two Arrays in two dimensional Array? - ios

I am new at iOS Dev. I want to save two different arrays (array1 & array2) in 2 dimensional array. I know how to save data directly in two dimensional array but can't by save two different arrays in one.
NSString* path = [[NSBundle mainBundle] pathForResource:#"Aasvogel" ofType:#"txt"];
NSString* content = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:NULL];
NSArray* foo = [content componentsSeparatedByString: #","];
NSMutableArray *array1 = #[], *array2 = #[];
for ( int i = 0; i < [foo count]; i++ )
{
NSString* day = foo[i];
if ( i % 2 == 0 ) { [array1 addObject:day];}
else { [array2 addObject:day];}
}
// and here i have populated two arrays (array1 and array2)
// Now i want to save these arraya in below two dimensional array (dataArray) atIndex:0 and at Index:1
NSMutableArray *dataArray = [[NSMutableArray alloc] initWithCapacity: 2];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"e",
#"el",
#"ale",
#"vela",
#"gavel",nil] atIndex:0];
[dataArray addObject:[NSMutableArray arrayWithObjects:#"Represents 50 in Roman numeral",
#"Building Wing",
#"Pub Brew",
#"Thin Parchment or membranes",
#"chairperson's hammer",nil] atIndex:1];

I have recently implemented 2D array into my application. Please check below code which is available at 2DArray
int capacity;
#property (nonatomic, strong) NSMutableArray *outerArray;
#define kCRL2DArrayEmptyKey #"kCRL2DArrayEmptyKey"
- (id) initWithRows:(int)x columns:(int)y
{
if (self = [super init])
{
capacity = y;
self.outerArray = [NSMutableArray array];
for (int i = 0; i < x; i++) {
NSMutableArray *innerArray = [NSMutableArray array];
for (int j = 0; j < y; j++) {
[innerArray addObject:kCRL2DArrayEmptyKey];
}
[self.outerArray addObject:innerArray];
}
}
return self;
}

you can try this
NSArray * firstArray, *secondArray;
NSArray * mainArray= [[NSArray alloc]initWithObjects: firstArray, secondArray, nil];

I am not sure about 2-dimensional array in iOS but if I were you I would be saved the two arrays within a dictionary such as
NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];
[dict setvalue:yourArray forKey:#"FirstArray"];
[dict setvalue:yourSecondArray forKey:#"SecondArray"];
And Use it accordingly.

There’s no such thing as a two (or more) dimensional NSArray. If you genuinely need an n-dimensional array object in iOS or OS X, you can of course roll your own, or you could instead create an NSArray of NSArray instances (which are columns and which are rows is entirely up to you). In that case, you could e.g. add items by doing
[[outerArray objectAtIndex:0] addObject:#"Foo"];
[[outerArray objectAtIndex:1] addObject:#"Bar"];
That said, for the problem you are tackling, it looks to me as if an NSDictionary might be more appropriate, e.g. with keys #"e", #"el" and values #"Represents 50 in Roman numerals", #"Building Wing".
If your concern is that the keys of NSDictionary are not held in sorted order, you can always extract the keys as an array and sort them. Or, if the keys change regularly, you might want to use a more sophisticated approach (e.g. keeping a separate sorted array of keys and inserting them into the right place when adding to the NSDictionary).
Also, you know that in modern Objective-C you can write e.g.
#[ #"a", #"b", #"c" ]
or
#{ #"a": #1, #"b": 2 }
rather than the very verbose forms you're using above?

this is how u add anything in a 2d array i.e an Array of arrays in objective-c
NSMutableArray *array 1 = [[NSMutableArray alloc]init];
NSMutableArray *array 2;
for(int col = 0;col <5;col++){
array2 = [[NSMutableArray alloc]init];
for(int row = 0;row<5;row++){
[array2 addObject:myItems];
}
[array1 addObject:array2];
}
hope this helps

use for loop to generate 2d array from 2 different array,
follow this stracture
int i, j;
for(i = 0; i < nrows; i++)
{
for(j = 0; j < ncolumns; j++)
array[i][j] = 0;
}
}
May be it will help you

Related

How to add values or add object into NSArray in Objective C using for loop?

Well this is my code:
NSDictionary *dicto;
NSString *ndccode;
NSString *string=#" ";
for (int i=0; i<array.count; i++) {
dicto=[array objectAtIndex:i];
ndccode=[dicto objectForKey:#"NDCCode"];
string=[string stringByAppendingString:ndccode];
string=[string stringByAppendingString:#"\n"];
NSLog(#"%#",string);
}
NSLog(#"%#",string);
In the above code, i have values in dicto nsdictionary which loops one by one value and assigns to ndccode which is string. Then I am adding to string so that I can append it to the next line.
output :
name1
name2
name3
.....
Instead of assigning to the string. I want to assign it to an array.Could you please tell me how to assign it to an array for this example,since it is in loop. I want to use the array for later purposes.
Thank you in advance.
NSDictionary *dicto;
NSString *ndccode;
NSMutableArray *outputArray=[NSMutableArray new];
for (int i=0; i<array.count; i++) {
dicto=[array objectAtIndex:i];
ndccode=[dicto objectForKey:#"NDCCode"];
[outputArray addObject:ndccode];
}
or even more succinctly
NSArray *outputArray = [array valueForKey:#"NDCCode"];

Trying to create an array of dictionaries, keep getting the same dictionary repeated in the array

I'm trying to use NSData to pull information out of a text file, and then load it into a dictionary.
First I create a string of the text file, and load each record into an array.
Then I break apart the each record into individual data elements.
The problem I'm having is that when the dictionary is fully populated, I then use addObject to load it into the array, which it does do successfully. The problem is that when the next loop creates a new dictionary, the same dictionary gets loaded into the array, and I end up an array of all the same dictionaries, instead of multiple different dictionary objects.
I'm guessing there is some simple mistake I'm making that is causing this error. Any help would be appreciated.
NSString *clientListFile = [NSURL URLWithString: #"/textfile"];
NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];
NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];
NSString *returnDelimiter = #"\n";
NSString *commaDelimiter = #",";
NSString *exclamationDelimiter = #"!";
NSArray *keysAndObjects = [[NSArray alloc]init];
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc]init];
NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
for (int i = 0; i < [sentenceArray count]; i=i+1) {
[clientList removeAllObjects]; //to start with a fresh dictionary for the next iteration
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (int j = 0; j < [attributes count]; j = j+1) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}
When I used NSLog to see what's in the dictionary, I mulitple objects of the same dictionary repeated, even though up earlier in the iteration, I can see that the code is creating separate and unique dictionaries.
Instead of this line
[clientListOfDictionaries addObject:clientList];
you can have
[clientListOfDictionaries addObject:[[NSArray alloc] initWithArray:clientList];
That way you will be adding new arrays to clientListOfDictionaries instead of the same one.
Move this line:
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
to just after the first for loop line and then delete the line:
[clientList removeAllObjects];
It's important to create a new dictionary for each iteration.
You should also delete the following line:
NSArray *keysAndObjects = [[NSArray alloc]init];
and change:
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
to:
NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
You are allocated and initialising your clientList dictionary outside of the for loop, so you only have one dictionary, which you are storing in your array multiple times. Adding the dictionary to the array does not copy it, it merely adds a pointer to the object.
you need to move
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
inside your first for loop in place of
[clientList removeAllObjects];
Also, componentsSeparatedByString: returns an NSArray, so you don't need to allocate and initialise one. You can simply define the variable -
NSArray *keysAndObjects;
Because you're using the same clientList variable for each iteration of the loop. You need to create a whole new dictionary object each time.
Try this modified code:
NSData *clientListDataFile = [NSData dataWithContentsOfFile:clientListFile];
NSString *clientListString = [[NSString alloc]initWithBytes:[clientListDataFile bytes] length:[clientListDataFile length] encoding:NSUTF8StringEncoding];
NSString *returnDelimiter = #"\n";
NSString *commaDelimiter = #",";
NSString *exclamationDelimiter = #"!";
NSArray *keysAndObjects = nil;
NSMutableArray *clientListOfDictionaries = [[NSMutableArray alloc] init];
NSArray *sentenceArray = [clientListString componentsSeparatedByString:returnDelimiter];
for (NSUInteger i = 0; i < [sentenceArray count]; ++i) {
NSMutableDictionary *clientList = [[NSMutableDictionary alloc] init]; //to start with a fresh dictionary for the next iteration
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (NSUInteger j = 0; j < [attributes count]; ++j) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}
An alternate option, though likely less efficient, is to to change the line:
[clientListOfDictionaries addObject:clientList];
to
[clientListOfDictionaries addObject:[clientList copy]];
That lets you keep using the same clientList variable, since you're adding a copy of it to the clientListOfDictionaries array. I just point that out because it might help you understand what's going on.
Also, note that I changed this line for you:
NSArray *keysAndObjects = [[NSArray alloc]init];
to
NSArray *keysAndObjects = nil;
Because it's just a pointer that is set by your call to componentsSeparatedByString, you don't need to allocate an array for it. That array will just vanish in your first iteration of the loop.
Should be added the new dictionary to array. Otherwise it will not add to an array. Every object in array have same dictionary mapping. So it will give you the same dictionary value. Create new dictionary for every object and add to array.
for (int i = 0; i < [sentenceArray count]; i=i+1) {
NSMutableDictionary *clientList = [[NSMutableDictionary alloc]init];
NSString *recordSentence = [sentenceArray objectAtIndex:i];
NSArray *attributes = [recordSentence componentsSeparatedByString:commaDelimiter];
for (int j = 0; j < [attributes count]; j = j+1) {
NSString *pairsOfItems = [attributes objectAtIndex:j];
//a small arry, of only two objects, the first is the key, the second is the object
NSArray *keysAndObjects = [pairsOfItems componentsSeparatedByString:exclamationDelimiter];
[clientList setObject:[keysAndObjects lastObject] forKey:[keysAndObjects firstObject]];
}
[clientListOfDictionaries addObject:clientList];
}

NSMutableArray with int values from 1 to 100

This should be dead easy, but somehow it doesn't want to work for me. Using iOS 7 and XCode 5.
All I'm trying to do is create an array with values from 1 to 100.
NSMutableArray *array;
for (int i = 0; i < 100; i++)
{
[array addObject:i];
}
This doesn't work. I get a "Implicit conversion of 'int' to 'id' is disallowed with ARC.
I get it, I can't add primitive types to an NSMutableArray.
[array addObject:#i];
This doesn't work either. I get a "unexpected '#' in program"
[array addObject:[NSNumber numberWithInt:i]];
[array addObject:[NSNumber numberWithInteger:i]];
(either case) This "works" (compiles) but it really doesn't "work". The problem with this is that the value from NSNumber is really not a 1-100. What I get for each row is "147212864", 147212832", "147212840"...not what I want.
Lastly:
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
{
[array addObject:i];
}
This also doesn't compile. I get an error on the i++. "Arithmetic on pointer to interface 'NSNumber', which is not a constant size for this architecture and platform"
Any suggestions on how to do this extremely simple thing on obj-c?
Either one of these should work:
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
or
NSMutableArray *array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[array addObject:[NSNumber numberWithInt:i]];
}
Here are the reasons why your code snippets did not work:
[array addObject:i] - You cannot add primitives to Cocoa collections
[array addObject:#i] - You forgot to enclose the expression i in parentheses
NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++ - You cannot increment NSNumber without "unwrapping" its value first.
If memory serves, I think you're simply missing parenthesis around the NSNumber shorthand expression.
NSMutableArray *array = [[NSMutableArray alloc] init];
for (NSUInteger i = 0; i < 100; i++)
{
[array addObject:#(i)];
}
Minimally, #i should be #(i) as described here. You are also forgetting to allocate and initialise your array
NSMutableArray *array = [[NSMutableArray alloc] init];
for (int i = 0; i < 100; i++) {
[array addObject:#(i)];
}
And since you are getting: "147212864", 147212832", "147212840"...not what I want., I think you are probably printing out your information wrongly or because the array is unallocated, that's simply garbage. Can you show us how you are outputting?
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *myNum;
for (int i = 0; i < 100; i++) {
myNum = [[NSNumber alloc]initWithInt:i];
[array addObject:myNum];
}
NSLog(#"%#", array); // 1 - 99 as expected
Worked for me :)
Just saying: Turn on all reasonable warnings in your Xcode project. Then read what the warnings are saying and do something about them. When you write something like
for (NSNumber *i = 0; i < [NSNumber numberWithInteger:100]; i++)
What does a for loop do? An object is in the end a pointer. So you initalise i to nil. Then you compare a pointer with a random pointer: [NSNumber numberWithInteger:100] returns a pointer to an object which could be anywhere in memory, and you compare pointers. Next the i++: No, you can't increment a pointer to an NSNumber. It doesn't make sense.

Trying to make NSMutableArray of dictionaries(logical mistake)

I am trying to make an Array of dictionaries
but something going wrong I have a mistake (logical) in my code and I can't figure out it for 2 hours, (I am new to iOS development , so maybe some experienced eye can see it fast?)
here is my code
Edited: code Update
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
//get all contacts names
NSMutableArray* EmailArrayPerPerson = [[NSMutableArray alloc]init];
NSMutableArray* PhoneArrayPerPerson = [[NSMutableArray alloc]init];
for (int i = 0; i < ABAddressBookGetPersonCount(addressBook); i++)
{
NSMutableDictionary *ContactsDetails = [NSMutableDictionary dictionary];
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
NSString *contact = (__bridge NSString *)(ABRecordCopyCompositeName(ref));
NSLog(#"%#",contact);//contact is good here
ContactsDetails = [NSMutableDictionary dictionary];
[ContactsDetails setObject:contact forKey:#"CName"];
ABMultiValueRef emails = ABRecordCopyValue(ref, kABPersonEmailProperty);
[EmailArrayPerPerson removeAllObjects];
NSLog(#"dictionary is:%#",[ContactsDetails objectForKey:#"CName"]);
for (CFIndex j=0; j < ABMultiValueGetCount(emails); j++)
{
NSString* email = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(emails, j));
[EmailArrayPerPerson addObject:email];
}
[ContactsDetails setObject:EmailArrayPerPerson forKey:#"CEMails"];
ABMultiValueRef multi = ABRecordCopyValue(ref, kABPersonPhoneProperty);
[PhoneArrayPerPerson removeAllObjects];
for (CFIndex j=0; j < ABMultiValueGetCount(multi); j++)
{
NSString* phone = (NSString*)CFBridgingRelease(ABMultiValueCopyValueAtIndex(multi, j));
[PhoneArrayPerPerson addObject:phone];
}
[ContactsDetails setObject:PhoneArrayPerPerson forKey:#"CPhones"];
NSLog(#"dictionary is:%#",ContactsDetails);
[Contacts addObject:ContactsDetails];
[Contacts insertObject:ContactsDetails atIndex:i];
NSLog(#"%#",Contacts);
}
NSLog(#"%d",[Contacts count]);
Contacts is my mutableArray, but when I am printing it
it always has the values of the last dictionary at all of his indexes.
when I am printing the dictionary in each iteration , I get the correct values inside.
Please give it a look help me to figure out what is wrong there.
I did mix of all answers , now it is partially working , I getting distinct Names , but mails and phones are still same for all
You're only ever creating one dictionary, and then modifying it in every iteration. Your final result contains the same dictionary N times, not N copies of the last dictionary.
You're doing this, basically:
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
NSMutableArray *dictionaries = [NSMutableArray array];
for (NSInteger i = 0; i < 10; i++) {
dict[#"something"] = #(i);
[dictionaries addObject:dict]; // adding the same dictionary you added last time
}
You want to be doing this:
NSMutableArray *dictionaries = [NSMutableArray array];
for (NSInteger i = 0; i < 10; i++) {
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
dict[#"something"] = #(i);
[dictionaries addObject:dict]; // adding the newly created dictionary
}
Side note...don't name your variables in Uppercase. In Objective-C, uppercase identifiers are used for class names. It's not technically wrong, but it's against the standard coding conventions for the language, which makes the code harder to read for other developers.
Try replacing each "remove object call," for example
[ContactsDetails removeAllObjects];
[EmailArrayPerPerson removeAllObjects];
with a re-instantiation, i.e.
ContactDetails = [NSMutableDictionary dictionary];
EmailArrayPerPerson = [[NSMutableArray alloc]init];
because you're essentially placing the same objects in each slot in your array repeatedly. You need to create new objects for each iteration.
Put this line of code in side your for loop
NSMutableDictionary *ContactsDetails = [NSMutableDictionary dictionary];

converting a onedimensional array to 2-d array having the specified number of columns

i am passing one one dimensional array having elements "1,2,3,4,5,6,7"
and in my code i want to convert this array into a 2-dimensional array .
The number of columns of the 2-d array will be specified by user .
say if am setting the columns value to 3
then the output 2-d array should be in the format
123
456
7
.m file of my class
-(NSMutableArray *)OneToTwoDimensionalArray:(NSMutableArray *)values :(NSInteger)columns
{
NSMutableArray * twoDimensional=[[NSMutableArray alloc]initWithCapacity:columns];
for(int i=0;i<columns;i++)
{
[twoDimensional insertObject:values atIndex:i];
}
return twoDimensional;
}
viewcontroller.m file
EPArray *arr=[[EPArray alloc]init];
int columns=4;
arr1=[[NSMutableArray alloc]initWithObjects:#"1",#"2",#"3",#"4",#"5",#"6",#"7",nil];
NSMutableArray *finalresult=[arr OneToTwoDimensionalArray:arr1 :columns];
for(int i=0;i<columns;i++)
{
NSLog(#"%#",[finalresult objectAtIndex:i]);
}
Try this,
NSArray *array = #[#"1", #"2", #"3", #"4", #"5", #"6", #"7"];
int noOfColumns = 3;
NSMutableArray *outerArray = [[NSMutableArray alloc] init];
for (int counter = 0; counter < [array count]; counter = counter + noOfColumns) {
NSMutableArray *innerArray = [[NSMutableArray alloc] init];
for (int arrayIndex = counter; ((arrayIndex < counter + noOfColumns) && (arrayIndex < [array count])); arrayIndex++) {
[innerArray addObject:array[arrayIndex]];
}
[outerArray addObject:innerArray];
}
NSLog(#"outerArray = %#", outerArray);
Here outerArray will give the 2 dimensional array with the provided column value. The above code is readable and easy to maintain especially if you want to make some quick changes.
Output:
outerArray = (
(
1,
2,
3
),
(
4,
5,
6
),
(
7
)
)
Next to my other answer — that I would favor — I want to offer another solution, that uses more traditional C-style programming but is quite readable.
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *newArray = [NSMutableArray array];
NSUInteger columnIdx = 0;
for (NSUInteger count = 0; count < [array count]; ++count) {
if (columnIdx == 0) {
[newArray addObject:[NSMutableArray array]];
}
NSMutableArray *lastArray = [newArray lastObject];
[lastArray addObject:array[count]];
columnIdx = (++columnIdx)%columnWidth;
}
newArray now contains the subarrays as required.
note, that also this solution uses the modulo operator columnIdx = (++columnIdx)%columnWidth;.
instead of this you also could write
++columnIdx;
if(columnIdx == columnWidth) columnIdx = 0;
NSUInteger columnWidth = 3;
NSArray *array = #[#1, #2, #3, #4 ,#5, #6, #7];
NSMutableArray *mArray =[NSMutableArray array];
[array enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % columnWidth == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
mArraynow contains 3 arrays with
(
(
1,
2,
3
)
,
(
4,
5,
6
)
,
(
7
)
)
This code uses the modulo operator that finds the remainder of division of one number by another.
if (idx % 3 == 0) {
[mArray addObject:[NSMutableArray array]];
}
if there is no remainder, it must be the index 0,3,6,…. In such a case, a new array is added to the outer array. the object are always added to the last array.
Also note that using enumerateObjectsUsingBlock: should be faster than using c-style for (for(int i=0;i<columns;i++)) or even fast enumeration.
I added a second answer that uses only C-constructs rather than blocks, but I'd favor this one.
and — of course — you should consider using a category on NSArray
#interface NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width;
#end
#implementation NSArray (Columns)
-(NSArray *)arrayOfArraysWithColumnWidth:(NSUInteger)width
{
NSAssert(width > 0, #"width need to be 1 or greater");//sanity check
NSMutableArray *mArray =[NSMutableArray array];
[self enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if (idx % width == 0) {
[mArray addObject:[NSMutableArray array]];
}
[[mArray objectAtIndex:[mArray count]-1] addObject:obj];
}];
return mArray;
}
#end
You would use it like:
NSArray *numbers = [#[#1, #2, #3, #4 ,#5, #6, #7] arrayOfArraysWithColumnWidth:3];

Resources