dublintech
dublintech

Reputation: 17785

Getting iteration counter in nested for loop

I want a counter to keep count how many iterations in total I have done. I do:

counter = 0;
for i, item in enumerate(items):
    for j, anotheritem in enumerate(anotheritems):
        counter += 1;

But I can't help asking is there a more pythonic way?

Upvotes: 1

Views: 2745

Answers (3)

Andy Hayden
Andy Hayden

Reputation: 375475

I would say the most pythonic way is to record i and j rather than count, since the tuple (i,j) has much more meaning than count - you can calculate count from (i,j)!

for i, item in enumerate(items):
    for j, anotheritem in enumerate(anotheritems):
        where_i_am = (i,j)
        # count = i*len(anotheritems) + j + 1

total_iterations = len(items) * len(anotheritems) # equivalently (i+1) * (j+1)

Upvotes: 3

Phil H
Phil H

Reputation: 20141

for counter,ijpair in enumerate(itertools.product(enumerate(items),enumerate(other))):
    i,j = ijpair
    //... do stuff

As Codemonkey points out, we're not increasing readability here, and for the explicit use stated, it's not really an improvement. However, the enumerate and itertools.product expressions are all generators/iterators, so they can be passed to other functions like map to be used there. So you could filter for wherever the item and otheritem were the same value:

allelements = itertools.product(items, others)
sameys = itertools.ifilter(lambda a: a[0]==a[1], allelements)

And now sameys has exactly the same structure as allelements. The point is that the whole iterable set becomes an iterator expression, rather than being a loop construct, which can be more easily passed around.

Upvotes: 1

Hubro
Hubro

Reputation: 59333

It's simple and readable, that's about as Pythonic as it gets (apart from the semi-colons.)

My only advice would be to give i and j more descriptive names if you start putting more code into those loops.

Upvotes: 4

Related Questions