Counting nested loop iterations

D

Derek Basch

What is the best way to count nested loop iterations? I can only figure
to use an index but that seems kludgy.

index = 0
for animal in zoo:
for color in animal:
index += 1

Thanks,
Derek Basch
 
F

Fredrik Lundh

Derek said:
What is the best way to count nested loop iterations? I can only figure
to use an index but that seems kludgy.

index = 0
for animal in zoo:
for color in animal:
index += 1

what's kludgy with using a counter to count things ?

(the real question here is of course why you need the counter. what's
the loop doing? if the code you posted is all you have, you can replace
it with index = sum(len(animal) for animal in zoo), but I assume you want
to do more stuff in there...)

</F>
 
J

Jeffrey Schwab

Derek said:
What is the best way to count nested loop iterations? I can only figure
to use an index but that seems kludgy.

index = 0
for animal in zoo:
for color in animal:
index += 1

Depending on the types of the containers in question, you could use:

len(zoo) * len(animal)
 
D

Derek Basch

Fredrik said:
what's kludgy with using a counter to count things ?

Ohhh, nothing in particular. Just seeing if there is a better way to do
it.
(the real question here is of course why you need the counter. what's
the loop doing? if the code you posted is all you have, you can replace
it with index = sum(len(animal) for animal in zoo), but I assume you want
to do more stuff in there...)

</F>

Yes, I am doing more. Your example assumes that all that animals have
the same amount of colors. Not a bad assumption considering I didn't
say anything about that. Looks like good old counters are they way to
go then.
 
D

Derek Basch

Depending on the types of the containers in question, you could use:
len(zoo) * len(animal)

I think this would give me the total iterations but I wouldn't be able
to get a running count. Correct?

Thanks for the reply,
Derek Basch
 
C

Caleb Hattingh

Hi Derek

I went for an embarrassingly long time without knowing about
"enumerate()". It doesn't directly answer your question about counting
*within* nests, but I am going to tell you this on the off chance you
don't know yet (and apologies if you do):

This:

count = 0
for animal in zoo:
a = animal
anum = count
count = count + 1

IS a kludge, when you have this available to you:

for count, animal in enumerate(zoo):
a = animal
anum = count

I won't say how long it took me to start using list comprehensions :)

regards
Caleb
 
K

Kent Johnson

Derek said:
Yes, I am doing more. Your example assumes that all that animals have
the same amount of colors.

No, it doesn't. Fredrik wrote
index = sum(len(animal) for animal in zoo)

The expression (len(animal) for animal in zoo) yields a sequence of the
lengths of the individual animals; passing this to sum() gives the total
count.

Kent
 
D

Duncan Booth

Derek said:
index = 0
for animal in zoo:
for color in animal:
index += 1
# assuming there is something more goes here...
You could do this, but it kind of depends what the loop *really* looks
like:

for index, color in enumerate(color
for animal in zoo
for color in animal):
# the something more goes here.
pass
 
C

Carl Banks

Derek said:
What is the best way to count nested loop iterations? I can only figure
to use an index but that seems kludgy.

index = 0
for animal in zoo:
for color in animal:
index += 1

I don't know if it's kludgy, but I do prefer to set counters in the for
statement whenever I can. If I were using 2.4, I might try writing
something like:

for i,(animal,zoo) in enumerate((animal,zoo) for animal in zoo for
color in animal):
pass

or maybe break it down a little for clarity:

aciter = ((animal,zoo) for animal in zoo for color in animal)
for i,(animal,zoo) in enumerate(aciter):
pass

But even the clear version isn't as nearly clear and straightforward as
the nested fors with the counter. I wouldn't forsake that clarity just
so it isn't "kludgy".


Carl Banks
 
D

Derek Basch

Carl said:
But even the clear version isn't as nearly clear and straightforward as
the nested fors with the counter. I wouldn't forsake that clarity just
so it isn't "kludgy".


Carl Banks

Yeah, looks like using the counters is clearer. Thanks for the opinions
everyone!

Derek Basch
 
J

Jeffrey Schwab

Derek said:
I think this would give me the total iterations but I wouldn't be able
to get a running count. Correct?

Correct. If you need a running count, maintain a counter (or enumerate()).
 
J

Joel Hedlund

for index, color in enumerate(color
for animal in zoo
for color in animal):
# the something more goes here.
pass

I've been thinking about these nested generator expressions and list
comprehensions. How come we write:

a for b in c for a in b

instead of

a for a in b for b in c

More detailed example follows below.

I feel the latter variant is more intuitive. Could anyone please explain the
fault of my logic or explain how I should be thinking about this? Or point me
to somewhere where I can read up on this?

Cheers,
Joel Hedlund



More detailed example:
>>> c = [[1,4,8],[2,5,7]]
>>> [a for b in c for a in b] [1, 4, 8, 2, 5, 7]
>>> del a,b,c
>>> c = [[1,4,8],[2,5,7]]
>>> [a for a in b for b in c]

Traceback (most recent call last):
File "<pyshell#30>", line 1, in -toplevel-
[a for a in b for b in c]
NameError: name 'b' is not defined
 
F

Fredrik Lundh

Joel said:
I've been thinking about these nested generator expressions and list
comprehensions. How come we write:

a for b in c for a in b

instead of

a for a in b for b in c

More detailed example follows below.

I feel the latter variant is more intuitive. Could anyone please explain the
fault of my logic or explain how I should be thinking about this?

out = [a for b in c for a in b]

can be written

out = [a
for b in c
for a in b]

which is equivalent to

out = []
for b in c:
for a in b:
out.append(a)

in other words, a list comprehension works exactly like an ordinary for
loop, except that the important thing (the expression) is moved to the
beginning of the statement.

</F>
 
J

Joel Hedlund

a list comprehension works exactly like an ordinary for
loop, except that the important thing (the expression) is moved to the
beginning of the statement.

Right. Thanks!
/Joel
 
J

Jeffrey Schwab

Fredrik said:
Joel said:
I've been thinking about these nested generator expressions and list
comprehensions. How come we write:

a for b in c for a in b

instead of

a for a in b for b in c

More detailed example follows below.

I feel the latter variant is more intuitive. Could anyone please explain the
fault of my logic or explain how I should be thinking about this?

out = [a for b in c for a in b]

can be written

out = [a
for b in c
for a in b]

which is equivalent to

out = []
for b in c:
for a in b:
out.append(a)

in other words, a list comprehension works exactly like an ordinary for
loop, except that the important thing (the expression) is moved to the
beginning of the statement.

Which is utterly counter-intuitive, the opposite of Perl, and remains
one of the most confusing and surprising things I have encountered in
Python so far.

And nobody start yelling that Python is not Perl. We all know Python is
not Perl, nor should it be. If you want different for the sake of
different, though, go try MOO or something. Here:

http://en.wikipedia.org/wiki/Esoteric_programming_language
 
D

Diez B. Roggisch

Which is utterly counter-intuitive, the opposite of Perl, and remains
one of the most confusing and surprising things I have encountered in
Python so far.

AFAIK stems from mathematics where you write things like

{y | \forall x \in X : \forall y \in x }

And so many people consider it pretty natural/intuitive. After all, we read
from left to right, and making something depend from something yet to be
introduced is counter-intuitive in my book. YMMV though.

Diez
 
D

Duncan Booth

Diez said:
AFAIK stems from mathematics where you write things like

{y | \forall x \in X : \forall y \in x }

And so many people consider it pretty natural/intuitive. After all, we
read from left to right, and making something depend from something
yet to be introduced is counter-intuitive in my book. YMMV though.
I think the problem is that y is used before the loop which creates it, but
x is used after the loop which creates it.

People can cope with the expanded loop form where everything it is used
after it is introduced, and it would appear that they also cope well with
the perl way of doing everything backwards, but moving the last element to
the front while keeping everything else in the 'correct' order seems to
confuse a lot of people.

Oh well, just wait until Python 2.5 comes out and we get people complaining
about the order of the new if statement.
 
D

Diez B. Roggisch

I think the problem is that y is used before the loop which creates it,
but x is used after the loop which creates it.

Well, you got me on that. Seems to be a matter of convention all the time.
People can cope with the expanded loop form where everything it is used
after it is introduced, and it would appear that they also cope well with
the perl way of doing everything backwards, but moving the last element to
the front while keeping everything else in the 'correct' order seems to
confuse a lot of people.

Oh well, just wait until Python 2.5 comes out and we get people
complaining about the order of the new if statement.

Sad, but true. But I'm a happy camper with list-comps and the new
if-expression :)

Diez
 
S

Scott David Daniels

Duncan said:
Oh well, just wait until Python 2.5 comes out and we get people complaining
about the order of the new if statement.

Or rather, the order of the new if _expression_.

--Scott David Daniels
(e-mail address removed)
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,768
Messages
2,569,574
Members
45,050
Latest member
AngelS122

Latest Threads

Top