Kolin Krewinkel
Kolin Krewinkel

Reputation: 1386

Multiple Loop Variables in For Statement in Obj-C

Is there a way to have multiple loop variables in a for statement? Here would be a hypothetical representation of what I'm talking about:

for (NSString *foo in bar; NSString *bob in example) {}

If not what is a good way to accomplish this?

Thanks,

Kolin

Upvotes: 1

Views: 392

Answers (3)

bbum
bbum

Reputation: 162712

Assuming blocks, an alternative:

NSAssert([foo count] == [bar count]);
[foo enumerateUsingBlock: ^(id fooObj, NSUInteger index, BOOL *stopFlag) {
    id barObj = [bar objectAtIndex: index];
    ... do stuff here ...
}];

Upvotes: 1

Mattia
Mattia

Reputation: 2281

Joshua is right that there's no way to do it with fast enumeration syntax but there's a couple of ways (at least) you can achieve something similar. Which approach you prefer depends on whether you're trying avoid the overhead of running the loop twice or whether you're trying to avoid the visual clutter of having two separate loops in your code.

Assuming you have two collections of NSStrings (they don't need to be NSArrays btw)

    NSArray* foo = [NSArray arrayWithObjects:@"bar1", @"bar2", @"bar3", @"bar4", @"bar5", nil];
NSArray* example = [NSArray arrayWithObjects:@"example1", @"example2", nil];

If you're looking to iterate over all the elements of both collections you can do the following:

    NSEnumerator* fooEnumerator = [foo objectEnumerator];
NSEnumerator* exampleEnumerator = [example objectEnumerator];

NSString *bar, *bob;

while ((bar = [fooEnumerator nextObject]) || (bob = [exampleEnumerator nextObject])) {
    if (bar) {
        NSLog(@"%@", bar);
    }
    if (bob) {
        NSLog(@"%@", bob);
    }
}

this will iterate over all of bar's elements first and then over all of example's elements (i.e. it will output: bar1, bar2, bar3, bar4, bar5, example1, example2).

if you want to minimize the number of iterations of the loop and don't necessarily need to run through all the elements of both collections you can try replacing the while loop above with:

while ((bar = [fooEnumerator nextObject]) && (bob = [exampleEnumerator nextObject])) {
    NSLog(@"%@", bar);
    NSLog(@"%@", bob);
}

This will loop through both collections simultaneously but will stop as soon as one of the collections runs out of elements (i.e. it will output: bar1, example1, bar2, example2)

Just as a note though, it's pretty rare that loops have a meaningful impact on performance so if this is all to avoid the runtime cost of two loops you're likely better served by other optimizations.

Upvotes: 4

Joshua Weinberg
Joshua Weinberg

Reputation: 28688

No, not using the fast enumeration syntax anyway.

Upvotes: 1

Related Questions