473,419 Members | 1,828 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,419 software developers and data experts.

Iterating over several lists at once

Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
I was wondering if one could write this more easily in some manner
using only 1 for loop.
What I mean is something like this:

for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3

Or maybe like this:

for x1 in l1, x2 in l2, x3 in l3:
print "do something with", x1, x2, x3

However, this code obviously doesn't work...
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).

Thanks in advance,
Gal

Dec 13 '06 #1
17 7136
"Gal Diskin" wrote:
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...

I was wondering if one could write this more easily in some manner
using only 1 for loop.
What I mean is something like this:

for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3
how about

for x1, x2, x3 in func(l1, l2, l3):
print x1, x2, x3

where func is defined as, say,

def func(l1, l2, l3):
return ((x1, x2, x3) for x1 in l1 for x2 in l2 for x3 in l3)

or if you prefer

def helper(l1, l2, l3):
for x1 in l1:
for x2 in l2:
for x3 in l3:
yield x1, x2, x3

</F>

Dec 13 '06 #2
Gal Diskin wrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3
What's wrong with this?

[...]
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).
def cartesian_product(l1, l2, l3):
for i in l1:
for j in l2:
for k in l3:
yield (i, j, k)

for (i, j, k) in cartesian_product(l1, l2, l3):
print "do something with", i, j, k

--
Roberto Bonvallet
Dec 13 '06 #3
"Gal Diskin" <ga********@gmail.comwrites:
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

This does look a little kludgy (untested):

for x1,x2,x3 in ((x1,x2,x3) for x1 in l1 for x2 in l2 for x3 in l3):
print "do something with", x1, x2, x3
Dec 13 '06 #4
Gal Diskin wrote:
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:
for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3
I was wondering if one could write this more easily in some manner
using only 1 for loop.
def nested_loops(*args):
assert args
if len(args) == 1:
for item in args[0]:
yield (item,)
else:
gap = len(args) // 2
for left in nested_loops(*args[:gap]):
for right in nested_loops(*args[gap:]):
yield left + right

if __name__ == "__main__":
for i, k in nested_loops("abc", "12"):
print i, k
for i, j, k in nested_loops("ab", "123", "xyz"):
print i, j, k

Be prepared for a significant performance hit.

Peter

PS: Did anybody say macro? No? I must be hallucinating...
Dec 13 '06 #5
Nothing seriously wrong, but it's not too elegent. Especially when the
number of lists you want to iterate over gets bigger (especially
because of the indentation in python). As you noticed (an phrased
better than me), what I was wondering is if there is a way to iterate
over the cartesian product, but without actually doing all n for loops
but using a single "for" loop.

Thanks for replying me.
On Dec 13, 3:58 pm, Roberto Bonvallet <Roberto.Bonval...@cern.ch>
wrote:
Gal Diskin wrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:
for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3What's wrong with this?

[...]
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).def cartesian_product(l1, l2, l3):
for i in l1:
for j in l2:
for k in l3:
yield (i, j, k)

for (i, j, k) in cartesian_product(l1, l2, l3):
print "do something with", i, j, k

--
Roberto Bonvallet
Dec 13 '06 #6
Gal Diskin schrieb:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
Heard about recursion?

def collect(L,*lists):
if not lists:
return [(x,) for x in L]
collection = []
for x in L:
for y in collect(lists[0],*lists[1:]):
collection.append((x,)+y)
return collection

for item in collect( l1, l2, l3):
func(*item)

Here is the same in generator form

def collect(L,*lists):
if not lists:
for x in L:
yield (x,)
else:
for x in L:
for y in collect(lists[0],*lists[1:]):
yield (x,)+y

( o.k - it required two nested for-loops in each implementation :)

Dec 13 '06 #7
Thanks, that's an improvment (your first way).
But I still wish I could find an even shorter (or more elegent) way of
doing it. (Well, I guess if I expect every wish I have to come true I
should at least wish for something more valuable.)

Thanks again,
Gal

On Dec 13, 3:58 pm, "Fredrik Lundh" <fred...@pythonware.comwrote:
"Gal Diskin" wrote:
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:
for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3
What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
I was wondering if one could write this more easily in some manner
using only 1 for loop.
What I mean is something like this:
for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3how about

for x1, x2, x3 in func(l1, l2, l3):
print x1, x2, x3

where func is defined as, say,

def func(l1, l2, l3):
return ((x1, x2, x3) for x1 in l1 for x2 in l2 for x3 in l3)

or if you prefer

def helper(l1, l2, l3):
for x1 in l1:
for x2 in l2:
for x3 in l3:
yield x1, x2, x3

</F>
Dec 13 '06 #8

Hi,

if you "needs to iterate over 3 lists at the same" and according your example
for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3

i has guessed that you need this (may be i was wrong):
a = (1,2,3, 1)
b = (4,5,6)
c = (7,8,9, 2, 3)

for x, y, z in zip(a, b, c):
print x, y, z
or this
for x, y, z in map(None, a, b, c):
print x,y,z
Try both examples with tuples that have various length, they have difference


Gal Diskin wrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
I was wondering if one could write this more easily in some manner
using only 1 for loop.
What I mean is something like this:

for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3

Or maybe like this:

for x1 in l1, x2 in l2, x3 in l3:
print "do something with", x1, x2, x3

However, this code obviously doesn't work...
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).

Thanks in advance,
Gal

--
Maksim Kasimov
Dec 13 '06 #9
Gal Diskin wrote:
On Dec 13, 3:58 pm, Roberto Bonvallet <Roberto.Bonval...@cern.ch>
wrote:
Gal Diskin wrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:
for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3What's wrong with this?
[...]
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).def cartesian_product(l1, l2, l3):
for i in l1:
for j in l2:
for k in l3:
yield (i, j, k)

for (i, j, k) in cartesian_product(l1, l2, l3):
print "do something with", i, j, k

Nothing seriously wrong, but it's not too elegent.
I wonder why you think that. Many people here would consider it the
height of elegance to take some complicated logic, writing a function
encompassing the complicated parts, and ending up with simpler logic.
That's what happens here.

The cartesian_product solution above is not much longer than this
syntax you proposed:

for (i,j,k) in (a,b,c):
use(i,j,k)

(You can make the function name shorter if you want.) What is it that
you find inelegant about this solution? Is it that you don't like
extra function sitting there? Just put it in a module and import it.

Especially when the
number of lists you want to iterate over gets bigger (especially
because of the indentation in python).
The function can be extended to allow arbitrary arguments. Here's a
non-minmal recursive version.

def cartesian_product(*args):
if len(args) 1:
for item in args[0]:
for rest in cartesian_product(*args[1:]):
yield (item,) + rest
elif len(args) == 1:
for item in args[0]:
yield (item,)
else:
yield ()

As you noticed (an phrased
better than me), what I was wondering is if there is a way to iterate
over the cartesian product, but without actually doing all n for loops
but using a single "for" loop.
Even if Python had a special syntax for it, it would still be looping
internally.

And there's almost no chance of there ever being a special syntax for
it. First of all, it's very straightforward to do with functional
solutions, as we've shown here. Second, compare the case of zip.
Iteration in parallel (such as you would do with zip) is a lot more
common than nested iteration (cartesian_product), but even parallel
iteration doesn't have a special syntax, and th BDFL had declared that
won't in Python 3.0.

The best you could hope for is a built in function like zip, and that's
doubtful. OTOH, something like this has decent shot of appearing in a
standard functional or iterator module of some sort.

Thanks for replying me.
You're welcome in advance. Also, one note about comp.lang.python
and/or python-list: it's conventional here to put replies beneath the
quoted text. This is for the benefit of future readers, so they don't
have read conversations in reverse order.
Carl Banks

Dec 13 '06 #10
at
Sorry for breaking into this thread, but I agree completely that any
unnecessary indentations should be avoided. For the same reason I advocate
that the following syntax should work:

for x in some_list if some_condition:
... code ...

in stead of

for x in some_list
if some_condition:
... code ...

All the best!

@

PS: maybe using 'sets' can help you out for a particular problem.
Gal Diskin wrote:
Nothing seriously wrong, but it's not too elegent. Especially when the
number of lists you want to iterate over gets bigger (especially
because of the indentation in python). As you noticed (an phrased
better than me), what I was wondering is if there is a way to iterate
over the cartesian product, but without actually doing all n for loops
but using a single "for" loop.

Thanks for replying me.
On Dec 13, 3:58 pm, Roberto Bonvallet <Roberto.Bonval...@cern.ch>
wrote:
>Gal Diskin wrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:
for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3What's wrong with this?

[...]
I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).def
cartesian_product(l1, l2, l3):
for i in l1:
for j in l2:
for k in l3:
yield (i, j, k)

for (i, j, k) in cartesian_product(l1, l2, l3):
print "do something with", i, j, k

--
Roberto Bonvallet
Dec 13 '06 #11
* at (at@tuko.nl) wrote:
Sorry for breaking into this thread, but I agree completely that any
unnecessary indentations should be avoided. For the same reason I advocate
that the following syntax should work:

for x in some_list if some_condition:
... code ...

in stead of

for x in some_list
if some_condition:
... code ...
It is possible to avoid the extra level of indentaion, but I think it's
much less readable than the 2-level verbose expresion:
>>a
[1, 2, 3, 4, 5, 6, 7]
>>for odd in (num for num in a if num % 2 == 1):
.... print odd
....
1
3
5
7

there is also continue, which I think is a good compromise:
>>for num in a:
.... if num % 2 == 0:
.... continue
.... print num
....
1
3
5
7

HTH (and not lead astray),

mike

Dec 14 '06 #12

Carl Banks wrote:
<snip>
>
The function can be extended to allow arbitrary arguments. Here's a
non-minmal recursive version.

def cartesian_product(*args):
if len(args) 1:
for item in args[0]:
for rest in cartesian_product(*args[1:]):
yield (item,) + rest
elif len(args) == 1:
for item in args[0]:
yield (item,)
else:
yield ()

Very nice.

Dec 14 '06 #13
John Henry wrote:
Carl Banks wrote:
<snip>
>The function can be extended to allow arbitrary arguments. Here's a
non-minmal recursive version.

def cartesian_product(*args):
if len(args) 1:
for item in args[0]:
for rest in cartesian_product(*args[1:]):
yield (item,) + rest
elif len(args) == 1:
for item in args[0]:
yield (item,)
else:
yield ()


Very nice.
another implementation of cartesian_product using 'reduce' to add
mystery ;-)

def star(outer, inner):
for rest in outer:
for item in inner:
yield rest + (item,)

def cartesian_product(*args):
return reduce(star, args, ((),))
>>list(cartesian_product("01","01","01"))
[('0', '0', '0'), ('0', '0', '1'), ('0', '1', '0'), ('0', '1', '1'),
('1', '0', '0'), ('1', '0', '1'), ('1', '1', '0'), ('1', '1', '1')]
>>>
Michael

Dec 14 '06 #14
Is this suppose to be a brain teaser or something?

Michael Spencer wrote:
John Henry wrote:
Carl Banks wrote:
<snip>
The function can be extended to allow arbitrary arguments. Here's a
non-minmal recursive version.

def cartesian_product(*args):
if len(args) 1:
for item in args[0]:
for rest in cartesian_product(*args[1:]):
yield (item,) + rest
elif len(args) == 1:
for item in args[0]:
yield (item,)
else:
yield ()

Very nice.
another implementation of cartesian_product using 'reduce' to add
mystery ;-)

def star(outer, inner):
for rest in outer:
for item in inner:
yield rest + (item,)

def cartesian_product(*args):
return reduce(star, args, ((),))
>>list(cartesian_product("01","01","01"))
[('0', '0', '0'), ('0', '0', '1'), ('0', '1', '0'), ('0', '1', '1'),
('1', '0', '0'), ('1', '0', '1'), ('1', '1', '0'), ('1', '1', '1')]
>>>

Michael
Dec 14 '06 #15


On Dec 13, 3:47 pm, "Gal Diskin" <gal.dis...@gmail.comwrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...

I was wondering if one could write this more easily in some manner
using only 1 for loop.
What I mean is something like this:

for (x1,x2,x3) in (l1,l2,l3):
print "do something with", x1, x2, x3

Or maybe like this:

for x1 in l1, x2 in l2, x3 in l3:
print "do something with", x1, x2, x3

However, this code obviously doesn't work...

I'd be very happy to receive ideas about how to do this in one loop and
with minimal initialization (if at all required).

Thanks in advance,Gal


Sorry for bumping this thread up. I just got back from a vacation and I
had to say thanks to all the people that took the time to answer me.

To Maksim - that's not what I meant, I want to iterate over the
cartesian product of the lists (all ordered tuples, _not_ the tuple
created from the first item in each list, then the tubple created from
the second item in each list... as your example does).

Thanks,
Gal

Dec 27 '06 #16

"Gal Diskin" <ga********@gmail.comwrote in message
news:11**********************@f1g2000cwa.googlegro ups.com...
>

On Dec 13, 3:47 pm, "Gal Diskin" <gal.dis...@gmail.comwrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
I don't see your previous article. Not sure if you are still looking for
a solution, but here's one:
>>[(x, y, z) for x in [1,2,3] for y in list('abc') for z in list('XY')]
[(1, 'a', 'X'), (1, 'a', 'Y'), (1, 'b', 'X'), (1, 'b', 'Y'), (1, 'c', 'X'),
(1, 'c', 'Y'), (2, 'a', 'X'), (2, 'a', 'Y'), (2, 'b', 'X'), (2, 'b', 'Y'),
(2, 'c', 'X'), (2, 'c', 'Y'), (3, 'a', 'X'), (3, 'a', 'Y'), (3, 'b', 'X'),
(3, 'b', 'Y'), (3, 'c', 'X'), (3, 'c', 'Y')]

This is a bit more compact, but I don't see anything wrong with what you
have.
Dec 27 '06 #17
In article <11**********************@16g2000cwy.googlegroups. com>,
"Gal Diskin" <ga********@gmail.comwrote:
Hi,
I am writing a code that needs to iterate over 3 lists at the same
time, i.e something like this:

for x1 in l1:
for x2 in l2:
for x3 in l3:
print "do something with", x1, x2, x3

What I need to do is go over all n-tuples where the first argument is
from the first list, the second from the second list, and so on...
Take a look at
http://mail.python.org/pipermail/pyt...er/104983.html

or

http://aspn.activestate.com/ASPN/Coo.../Recipe/159975

There's nothing magic about either -- fundamentally, you're still doing an
N^3 operation and it's going to be slow. You might want to stop and think
if there's some better algorithm than an exhaustive search of the entire
domain space for whatever it is that you're trying to do.
Dec 27 '06 #18

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

12
by: Matthew Wilson | last post by:
I'm playing around with genetic algorithms and I want to write a function that mutates an integer by iterating across the bits, and about 1 in 10 times, it should switch a zero to a one, or a one...
7
by: Dave Hansen | last post by:
OK, first, I don't often have the time to read this group, so apologies if this is a FAQ, though I couldn't find anything at python.org. Second, this isn't my code. I wouldn't do this. But a...
6
by: Gustaf Liljegren | last post by:
I ran into this problem today: I got an array with Account objects. I need to iterate through this array to supplement the accounts in the array with more data. But the compiler complains when I...
25
by: krbyxtrm | last post by:
hello i have this profile for iterating empty vectors: +0.3us (microsecond) on intel pentium 2.4Ghz can this added delay to my application be reduced? i mean near zero delay, its very important....
9
by: JJ | last post by:
I have a need to add several userid's (for example) to a table in an sql database. The usernames will all added to a listbox (or similar) and a 'submit' button will be clicked to send them to the...
9
by: Ben Rudiak-Gould | last post by:
Background: I have some structs containing std::strings and std::vectors of other structs containing std::strings and std::vectors of .... I'd like to make a std::vector of these. Unfortunately the...
4
RMWChaos
by: RMWChaos | last post by:
The next episode in the continuing saga of trying to develop a modular, automated DOM create and remove script asks the question, "Where should I put this code?" Alright, here's the story: with a...
3
by: Lie | last post by:
When you've got a nested loop a StopIteration in the Inner Loop would break the loop for the outer loop too: a, b, c = , , def looper(a, b, c): for a_ in a: for b_ in b: for c_ in c:...
4
by: mathieu | last post by:
Hi there, just trying to figure out how to iterate over two array without computing the len of the array: A = B = for a,b in A,B: # does not work ! print a,b
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.