Re: Simple way to traverse 2D array?
Re: Simple way to traverse 2D array?
- Subject: Re: Simple way to traverse 2D array?
- From: Graham Cox <email@hidden>
- Date: Tue, 24 Feb 2009 14:51:34 +1100
On 24/02/2009, at 1:21 PM, Ashley Perrien wrote:
It's a bit unclear from your description if what you have is really
a 3D array or a 2D array. Each of the combinations in your example
output has three dimensions, not two.
To recreate what I had described earlier:
NSArray *numbers = [NSArray arrayWithObjects: @"1", @"2", @"3", nil];
NSArray *letters = [NSArray arrayWithObjects: @"A", @"B", nil];
NSArray *colors = [NSArray arrayWithObjects: @"Red", @"White",
@"Blue", nil];
NSArray *primaryArray = [NSArray arrayWithObjects: numbers, letters,
colors, nil];
The primaryArray is being created in another method and being passed
in. In THIS case it has 3 arrays in it, but I can't assume it'll
always have 3.
- (void) combinations
{
NSArray* numbers = [NSArray arrayWithObjects:@"1", @"2", @"3", nil];
NSArray* letters = [NSArray arrayWithObjects:@"A", @"B", @"C",
@"D", nil];
NSArray* colours = [NSArray arrayWithObjects:@"Red", @"White",
@"Blue", nil];
unsigned i, j, k;
NSString* combo;
for( i = 0; i < [numbers count]; ++i )
{
for( j = 0; j < [letters count]; ++j )
{
for( k = 0; k < [colours count]; ++k)
{
int index = (i * [letters count] * [colours count]) + (j *
[colours count]) + k;
combo = [NSString stringWithFormat:@"combo%d: %@, %@, %@",
index + 1, [numbers objectAtIndex:i], [letters objectAtIndex:j],
[colours objectAtIndex:k]];
NSLog(@"%@", combo);
}
}
}
}
But this code assumes there will be 3 arrays (numbers, letters,
colors), what if that number is not known? It could be 3, it could
be 8. I could (fairly safely) assume that it will always be less
than 12 and then nest it as shown with lots of error checking but
that would be an unsightly mess.
Ashley Perrien
OK, I get what you mean now.
What you want to do is multiply all the arrays together, i.e. result =
m(0) x m(1) x..x m(n) where n is the number of arrays in your "primary
array" (that being the dimension of the result), and m being each
array contained therein.
The difficulty is defining what it means to "multiply" two objects. If
an array is being multiplied by a scalar, the result is a new array
containing the same number of objects as the original. If the array is
multiplied by another array, the result is a new array containing m x
n objects.
One solution that comes to mind is to create a "multiply" category for
NSObject, NSArray and maybe NSString if that's what you know your
objects are going to be. For each class you need to define what it
means to multiply it by another object, be it an array, another object
of its own kind or any other object. For strings for example it might
mean concatenating the strings or inserting them into a formatted
string. Once you've done that you can simply write something like:
result = 1;
for( each object in primaryArray )
result = [result multiplyBy:object];
Here's a very quick attempt at doing this - seems to work pretty well.
Note that in the case of multiplying one array by another, if either
array is empty it returns the other one. This is not strictly
mathematically correct as it implies that n x 0 = n, which is not
true. However this does simplify calling the code unconditionally (and
if it offends you, you can redefine the empty array == 1) since the
case of multiplying an array by a series of arrays is made to work
simply.
This isn't the only solution, but it's object-oriented and clean. Hope
it helps - interesting problem ;-)
--Graham
@interface NSArray (Multiply)
- (NSArray*) multiplyBy:(id) object;
- (NSArray*) multiplyByArray:(NSArray*) objects;
+ (void) testMultiplication;
@end
@interface NSObject (Multiply)
- (id) multiplyBy:(id) object;
@end
@interface NSString (Multiply)
- (NSString*) multiplyBy:(id) object;
@end
@implementation NSArray (Multiply)
- (NSArray*) multiplyByArray:(NSArray*) objects
{
// returns an array which is all the combinations of the objects in
the input array with the objects of self. To simplify things,
// the empty array is treated as equal to a constant of 1, i.e. array
* empty -> array, not -> empty.
if([self count] == 0 )
return objects;
else if([objects count] == 0 )
return self;
else
{
NSMutableArray* result = [NSMutableArray array];
unsigned i, j;
for( i = 0; i < [self count]; ++i )
{
for( j = 0; j < [objects count]; ++j )
[result addObject:[[self objectAtIndex:i] multiplyBy:[objects
objectAtIndex:j]]];
}
return result;
}
}
- (NSArray*) multiplyBy:(id) object
{
if([object isKindOfClass:[self class]])
return [self multiplyByArray:object];
else
{
NSMutableArray* array = [NSMutableArray array];
unsigned i;
for( i = 0; i < [self count]; ++i )
[array addObject:[[self objectAtIndex:i] multiplyBy:object]];
return array;
}
}
+ (void) testMultiplication
{
NSArray* numbers = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4",
nil];
NSArray* letters = [NSArray arrayWithObjects:@"A", @"B", @"C", nil];
NSArray* colours = [NSArray arrayWithObjects:@"Red", @"White",
@"Blue", nil];
NSArray* animals = [NSArray arrayWithObjects:@"Cat", @"Dog", nil];
NSArray* primary = [NSArray arrayWithObjects:numbers, letters,
colours, animals, nil];
unsigned i;
NSArray* result = [NSArray array]; // start with an empty array (==1)
to allow us to simply iterate the list below.
for( i = 0; i < [primary count]; ++i )
result = [result multiplyBy:[primary objectAtIndex:i]];
NSLog(@"%@", result);
}
@end
@implementation NSString (Multiply)
- (NSString*) multiplyBy:(id) object
{
// "multiplying" two strings returns the two strings separated by a
comma
return [NSString stringWithFormat:@"%@, %@", self, object];
}
@end
@implementation NSObject (Multiply)
- (id) multiplyBy:(id) object
{
#pragma unused(object)
// generally this needs to be implemented appropriately by specific
subclasses of NSObject so that the
// operation "multiply" can be defined to make sense. Currently
simply returns self, treating <object> as constant == 1
return self;
}
@end
Logged output of test method:
"1, A, Red, Cat",
"1, A, Red, Dog",
"1, A, White, Cat",
"1, A, White, Dog",
"1, A, Blue, Cat",
"1, A, Blue, Dog",
"1, B, Red, Cat",
"1, B, Red, Dog",
"1, B, White, Cat",
"1, B, White, Dog",
"1, B, Blue, Cat",
"1, B, Blue, Dog",
"1, C, Red, Cat",
"1, C, Red, Dog",
"1, C, White, Cat",
"1, C, White, Dog",
"1, C, Blue, Cat",
"1, C, Blue, Dog",
"2, A, Red, Cat",
"2, A, Red, Dog",
"2, A, White, Cat",
"2, A, White, Dog",
"2, A, Blue, Cat",
"2, A, Blue, Dog",
"2, B, Red, Cat",
"2, B, Red, Dog",
"2, B, White, Cat",
"2, B, White, Dog",
"2, B, Blue, Cat",
"2, B, Blue, Dog",
"2, C, Red, Cat",
"2, C, Red, Dog",
"2, C, White, Cat",
"2, C, White, Dog",
"2, C, Blue, Cat",
"2, C, Blue, Dog",
"3, A, Red, Cat",
"3, A, Red, Dog",
"3, A, White, Cat",
"3, A, White, Dog",
"3, A, Blue, Cat",
"3, A, Blue, Dog",
"3, B, Red, Cat",
"3, B, Red, Dog",
"3, B, White, Cat",
"3, B, White, Dog",
"3, B, Blue, Cat",
"3, B, Blue, Dog",
"3, C, Red, Cat",
"3, C, Red, Dog",
"3, C, White, Cat",
"3, C, White, Dog",
"3, C, Blue, Cat",
"3, C, Blue, Dog",
"4, A, Red, Cat",
"4, A, Red, Dog",
"4, A, White, Cat",
"4, A, White, Dog",
"4, A, Blue, Cat",
"4, A, Blue, Dog",
"4, B, Red, Cat",
"4, B, Red, Dog",
"4, B, White, Cat",
"4, B, White, Dog",
"4, B, Blue, Cat",
"4, B, Blue, Dog",
"4, C, Red, Cat",
"4, C, Red, Dog",
"4, C, White, Cat",
"4, C, White, Dog",
"4, C, Blue, Cat",
"4, C, Blue, Dog"
_______________________________________________
Cocoa-dev mailing list (email@hidden)
Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com
Help/Unsubscribe/Update your Subscription:
This email sent to email@hidden