Looping NSArray

Discussion in 'Mac Programming' started by cea, Apr 17, 2010.

  1. cea macrumors newbie

    Joined:
    Oct 26, 2009
    #1
    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 *= [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G"nil];
        
    NSArray *= [NSArray arrayWithObjects:@"1", @"2", @"3"nil];
        for (
    int i 0< [a count]; i++) {
            
    // dont know to go futher.
        
    }
     
  2. GorillaPaws macrumors 6502a

    GorillaPaws

    Joined:
    Oct 26, 2003
    Location:
    Richmond, VA
    #2
    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.
     
  3. cea thread starter macrumors newbie

    Joined:
    Oct 26, 2009
    #3
    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 *= [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G"nil];
        
    NSArray *= [NSArray arrayWithObjects:@"1", @"2", @"3"nil];
        
        
    NSMutableString *result = [[[NSMutableString allocinitautorelease];
        
        for (
    int i 0< [a count]; i++) {
            for (
    int j 0< [b count]; j++) {
                [
    result appendFormat:@"%@%@ ", [a objectAtIndex:i], [b objectAtIndex:j]];
            }
        } 
        
    NSLog (@"%@"result);
     
  4. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #4
    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.
     
  5. cea thread starter macrumors newbie

    Joined:
    Oct 26, 2009
    #5
    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
     
  6. cea thread starter macrumors newbie

    Joined:
    Oct 26, 2009
    #6
    PHP:
        NSArray *= [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G"nil];
        
    NSArray *= [NSArray arrayWithObjects:@"1", @"2", @"3"nil];
        
        
    NSMutableString *result = [[[NSMutableString allocinitautorelease];
        
        for (
    int i 0< [a count]; i++) {
            
    int x i;
            while (
    0) {
                
    int j = (% [b count]);
                
    / [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
     
  7. lee1210 macrumors 68040

    lee1210

    Joined:
    Jan 10, 2005
    Location:
    Dallas, TX
    #7
    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
     
  8. cea thread starter macrumors newbie

    Joined:
    Oct 26, 2009
    #8
    ahh thank you Lee, It was hard i got it:

    PHP:
        NSArray *= [NSArray arrayWithObjects:@"A", @"B", @"C", @"D", @"E", @"F", @"G"nil];
        
    NSArray *= [NSArray arrayWithObjects:@"1", @"2", @"3"nil];
        
        
    NSMutableString *result = [[[NSMutableString allocinitautorelease];
        
        for (
    int i 0< [a count]-1i++) {
                
    int j = (% [b count]);
                [
    result appendFormat:@"%@%@ ", [a objectAtIndex:i], [b objectAtIndex:j]];
            }
        
    NSLog (@"%@"result);
    A1 B2 C3 D1 E2 F3
     
  9. Sydde macrumors 68020

    Sydde

    Joined:
    Aug 17, 2009
    #9
    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
    
     

Share This Page