2

I am aware that two collections can be accessed simultaneously using

for i,j in zip([1,2,3],[4,5,6]):
    print i,j

1 4
2 5
3 6

What I would like to do is something like this:

for i,j in [[1,2,3],[4,5,6]]:
    print i,j

1 4
1 5
1 6
2 4
2 5
2 6
3 4
3 5
3 6

I want python to automatically create the nested for loop for me. I would like to avoid using many nested for loops in my code when the list dimension gets up to 5 or 6. Is this possible?

jamesbtate
  • 1,359
  • 3
  • 19
  • 25

3 Answers3

12

Try

for i, j in itertools.product([1, 2, 3], [4, 5, 6]):
    print i, j
Sven Marnach
  • 574,206
  • 118
  • 941
  • 841
  • Took a look at the docs and I need to upgrade to python 2.6. Appears to do exactly what I wanted though. Will check in 8 minutes. Thanks. – jamesbtate Jan 23 '11 at 21:58
  • @puddingfox: You can also copy the implementation from the [documentation](http://docs.python.org/library/itertools.html#itertools.product), but it will be less efficient than the Real Thing. – Sven Marnach Jan 23 '11 at 22:00
  • Itertools rocks. It is worth the time to learn the tools in that toolbox. – payne Jan 23 '11 at 22:42
1
>>> [[x,y] for x in [1,2,3] for y in [4,5,6]]
[[1, 4], [1, 5], [1, 6], [2, 4], [2, 5], [2, 6], [3, 4], [3, 5], [3, 6]]

It should be pretty easy to get what you want out of the resulting list.

aqua
  • 3,269
  • 28
  • 41
  • But that's harder to generalize for lists nested n times. –  Jan 23 '11 at 22:06
  • Is it? Maybe I don't quite understand but if you simply do `[[x,y,z] for x in [1,2,3] for y in [4,5,6] for z in [7,8,9]]` it should scale, no? – aqua Jan 23 '11 at 22:09
  • 1
    well it _does_ already look a little unwieldly compared to using product. Howver the big difference is that nested LC has the dimensions hardcoded - whereas product can work with any number of dimensions – John La Rooy Jan 23 '11 at 22:13
0

I've had some cases where the logic for what needs to be iterated over is rather complex -- so you can always break that piece out into it's own generator:

def it():
    i = 0
    for r in xrange(rows):
        for c in xrange(cols):
            if i >= len(images):
                return
            yield r, c, images[i], contents[i]
            i += 1

for r, c, image, content in it():
    # do something...

But typically I find just spelling simple nested loops out to be better than obfuscating what you're looping over into a call to some other code. If you have more than 2-3 loops nested, the code probably needs refactoring anyway.

Matt Billenstein
  • 678
  • 1
  • 4
  • 7