Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

cea

macrumors newbie
Original poster
Oct 26, 2009
22
0
I am thinking for awhile to solve this. I have 2 array and would like to have a result like this:
A1 B2 C3 D1 E2 F3 ...
Can you please help me, thanks!

PHP:
	NSArray *a = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", nil];
	NSArray *b = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
	for (int i = 0; i < [a count]; i++) {
		// dont know to go futher.
	}
 
Here's a hint. If you call objectAtIndex: on each of your array objects and you use your index variable i as the parameter, you will get out the pieces you need. I'll leave the rest for you to figure out.
 
Sorry for the typo, i meant:
A1 B2 C3 D1 E2 F3 ...

I use objectAtIndex and got:
A1 A2 A3 B1 B2 B3 ...
(this was my typo mistake which i do not mean):

PHP:
    NSArray *a = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", nil];
    NSArray *b = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
	
    NSMutableString *result = [[[NSMutableString alloc] init] autorelease];
	
    for (int i = 0; i < [a count]; i++) {
        for (int j = 0; j < [b count]; j++) {
            [result appendFormat:@"%@%@ ", [a objectAtIndex:i], [b objectAtIndex:j]];
        }
    } 
	NSLog (@"%@", result);
 
Sorry for the typo, i meant:
A1 B2 C3 D1 E2 F3 ...

I use objectAtIndex and got:
A1 A2 A3 B1 B2 B3 ...
(this was my typo mistake which i do not mean)

If you don't want A1 A2 A3 B1 B2 B3 then don't use two loops. Step through your design manually before writing code. Or step through the code you wrote manually, and see why it's not doing what you want.

You may think this is tedious, but it's very important that you visualize and understand exactly what your code is doing. I know of no better way to do that than performing it by yourself, by hand, as if you were the computer.

You should also familiarize yourself with the modulus operator, which is % in C. It's also called "remainder". There are other approaches, but calculating an array index modulo the smaller array size is the simplest. Modulo arithmetic is also called circular arithmetic, because it goes around in a circle. It's also called "clock arithmetic", because like seconds, minutes, and hours, it cycles around to its start point after reaching a maximum. That is, the minute after 58 is 59, but the minute after 59 is 0. That's modular arithmetic, where the modulus is 60.

One of the conceptually simple approaches is to extend the shorter array by repeating elements, until it's the same length as the longer one. So if you start with "1", "2", "3", and it needs to be length 7, then append a "1", then a "2", then a "3". By the time you reach the 4th item, you'll be at "1", because that's the first repeated item you appended. Continue until the length is correct. Although this is conceptually simple, it's unwise in practice, because you can't modify arrays whenever you feel like it. So you use modular (i.e. circular) arithmetic to make sure the shorter array indexes go around as many times as needed, but without actually extending the array.
 
I really didn't know about this "Modulo arithmetic" before. This is what i am often looking for. Can you please direct me how to use "Modulo arithmetic" in this example. Thanks
 
PHP:
	NSArray *a = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", nil];
    NSArray *b = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
    
    NSMutableString *result = [[[NSMutableString alloc] init] autorelease];
    
    for (int i = 0; i < [a count]; i++) {
		int x = i;
		while (x > 0) {
			int j = (x % [b count]);
			x = x / [a count];
			[result appendFormat:@"%@%@ ", [a objectAtIndex:i], [b objectAtIndex:j]];
		}
    } 
    NSLog (@"%@", result);

I still cannot get to work using "Modulo arithmetic", i got this:
B2 C3 D1 E2 F3 G1
 
You need one loop, no nesting required.

For your letter array, you want to get objects from index 0 to count-1. Your number array just needs to be accessed using the index of the letter array, mod count of this array.

-Lee
 
ahh thank you Lee, It was hard i got it:

PHP:
	NSArray *a = [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G", nil];
    NSArray *b = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
    
    NSMutableString *result = [[[NSMutableString alloc] init] autorelease];
    
    for (int i = 0; i < [a count]-1; i++) {
			int j = (i % [b count]);
			[result appendFormat:@"%@%@ ", [a objectAtIndex:i], [b objectAtIndex:j]];
		}
    NSLog (@"%@", result);

A1 B2 C3 D1 E2 F3
 
You would have to be a little messed up in the head to use a technique such as this, but a Synthetic Hybrid Data Structure can work quite well for a looping array. It would look something like this:

.h file
Code:
#import <Cocoa/Cocoa.h>
@interface CRLFLoopingArray : NSObject {

	id		prevEntry; // backward list link
	id		nextEntry; // forward list link
	
	id		theObject; // listed object
	
}

- (id)initWithArray:(NSArray *)objects;
- (id)value;
- (id)changeValue:(id)newValue; // returns the old value, autoreleased
- (id)nextEntry;
- (id)prevEntry;
- (int)count;
- (id)entryAtOffset:(int)offset;
// returns a value and advances the caller's pointer
- (id)valueNext:(CRLFLoopingArray **)srcRef;
// returns a value and backs up the caller's pointer
- (id)valuePrev:(CRLFLoopingArray **)srcRef;
// places a new entry after the reciever
- (id)addValue:(id)object; // value is retained
- (id)removeEntry; // returns the next entry
- (void)clear; // use instead of release to destroy a list

@end
.m file
Code:
#import "CRLFLoopingArray.h"

@implementation CRLFLoopingArray

- (id)init {
	if ( self = [super init] ) {
		// close object's list back to self
		nextEntry = self;
		prevEntry = self;
		theObject = nil;
	}
	return self;
}

- (id)initWithArray:(NSArray *)objects {
	NSEnumerator	*listScan = [objects objectEnumerator];
	id	CRLFReturn = nil;
	id	backLink;
	id	anObject;
	if ( self = [super init] ) {
		theObject = nil; // in case the array is empty
		CRLFReturn = self; // capture the beginning of the loop
		backLink = self;
		anObject = [listScan nextObject];
		while ( nil != anObject ) {
			theObject = [anObject retain]; // take and own the object
			anObject = [listScan nextObject];
			backLink = self;
			if ( nil != anObject ) {
				// add another entry for then next object
				nextEntry = [[CRLFLoopingArray alloc] init];
				self = nextEntry;
				prevEntry = backLink;
			}
		}
		// close up the loop
		nextEntry = CRLFReturn; 
		self = nextEntry;
		prevEntry = backLink;
	}
	return CRLFReturn;
}

- (id)value { return theObject; }

- (id)changeValue:(id)newObject {
	id	oldValue = theObject;
	if ( nil != oldValue ) [oldValue autorelease];
	theObject = newObject;
	return oldValue;
}

- (id)nextEntry { return nextEntry; }
- (id)prevEntry { return prevEntry; }

- (int)count {
	id	ctBase = self;
	int	theCt = 0;
	// loop through the loop until we get back to the first entry
	do {
		if ( nil != theObject ) theCt += 1 ;
		self = nextEntry;
	} while ( self != ctBase );
	return theCt;
}

- (id)entryAtOffset:(int)offset {
	int	ctOff;
	if ( 0 < offset ) {
		// positive offset - scan forward
		for ( ctOff = 0 ; ctOff < offset ; ctOff++ ) self = nextEntry;
	} else {
		// non-positive offset - scan backward
		for ( ctOff = 0 ; ctOff > offset ; ctOff-- ) self = prevEntry;
	}
	return self;
}

// returns a value and advances the caller's pointer
- (id)valueNext:(CRLFLoopingArray **)srcRef {
	*srcRef = nextEntry;
	return theObject;
}
// returns a value and backs up the caller's pointer
- (id)valuePrev:(CRLFLoopingArray **)srcRef {
	*srcRef = prevEntry;
	return theObject;
}

// places a new entry after the reciever
- (id)addValue:(id)object {
	id	linkUp = nextEntry; // return the same entry if object is nil
	id	dnLink = self;
	if ( nil != object ) {
		// hold the link
		// create a new entry
		nextEntry = [[CRLFLoopingArray alloc] init];
		// enter the object
		self = nextEntry;
		// set its value
		theObject = object;
		// and link it in
		nextEntry = linkUp;
		prevEntry = dnLink;
		// now change the next entry's back link to the new entry
		dnLink = self; 
		self = nextEntry;
		prevEntry = dnLink;
	}
	return dnLink; // return the new entry ( or the old one if object is nil )
}

- (id)removeEntry {
	id	cutEntry = self;
	id	entryLeft = nil; // returns nil if this is the last entry
	id	entryRight = prevEntry;
	// if either of the links is self, this is the only entry
	if ( prevEntry != self ) {
		// extricate this entry
		entryLeft =  nextEntry;
		// go back one;
		self = prevEntry;
		// link to the next one
		nextEntry = entryLeft;
		// go to that next one
		self = nextEntry;
		// link back to the previous one
		prevEntry = entryRight;
	} 
	[cutEntry release]; // release the receiver
	return entryLeft; // return the entry after it
}

- (void)clear {
	id	clearNext = self;
	id	toClear = self;
	// loop through the list using self as the start marker
	while ( nextEntry != clearNext ) {
		// move to the next entry
		self = nextEntry;
		// release the one just exited
		[toClear release];
		// mark this entry for release
		toClear = self;
	}
	[toClear release]; // release the last entry
}

- (void)dealloc {
	if ( nil != theObject ) [theObject release];
	[super dealloc];
}

@end
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.