1

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

2
  • 2
    So what happen if the number of elements are different? Commented Oct 31, 2010 at 10:59
  • In my case they're always the same number. Commented Oct 31, 2010 at 21:57

3 Answers 3

4

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.

Sign up to request clarification or add additional context in comments.

Comments

1

No, not using the fast enumeration syntax anyway.

2 Comments

Is there anything that I can do that has comparable results?
Depends more on what you're specifically trying to accomplish
1

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 ...
}];

1 Comment

Thanks..will try this when the minimum os is iOS4.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.