How do I increment a counter inside a while test of Python

41,010

Solution 1

The problem you can't do that way in Python is a restriction of Python syntax. Let's get what does while look like from documentation:

while_stmt ::=  "while" expression ":" suite
                ["else" ":" suite]

As You can see you must put expression before ":", while x += 1 is a statement (and statements doesn't return any value so cannot be used as a condition).

Here's what does this code look like in Python:

i += 1
while a[i] < v:
    if i == hi:
        break
    i += 1

Though it works, it's most likely not a Python way to solve your problem. When you have a collection and you want to use indices you have to look forward to redesigning your code using for loop and enumerate built-in function.

P.S.

Anyway, direct code porting between languages with absolutely different philosophies is not a good way to go.

Solution 2

The Java code sets i to the index of either the first element >= a[lo], or to hi, whichever appears first. So:

v = a[lo]
for i in range(lo+1, hi+1):
    if a[i] >= v:
        break

Solution 3

If you want to iterate over all the objects in a list or any "iterable" thing, use "for item in list". If you need a counter as well, use enumerate. If you want a range of numbers use range or xrange.

But sometimes you really do want a loop with a counter that just goes up which you're going to break out of with break or return, just like in the original poster's example.

For these occasions I define a simple generator just to make sure I can't forget to increment the counter.

def forever(start=0):
    count = start
    while True:
        yield count
        count += 1

Then you can just write things like:

for count in forever():
    if do_something() == some_value:
        break
return count
Share:
41,010
boardrider
Author by

boardrider

Updated on June 10, 2020

Comments

  • boardrider
    boardrider almost 4 years

    How would you translate the following Java idiom to Python?

    Comparable[] a, int lo, int hi;
    int i = lo, j = hi+1;
    Comparable v = a[lo];
    
    while (a[++i] < v) if (i == hi) break;
    

    My problem is that in the while test I cannot have a ++i or i += 1.

  • michelson
    michelson over 11 years
    BTW - I wouldn't call this a syntax limitation. It is a philosophical restriction that the language imposes.
  • boardrider
    boardrider over 11 years
    My code needs to check that "a[++i] < v" namely, i needs to be incremented prior to the test. The solution you present, does not do that (it checks a[i]).
  • Rostyslav Dzinko
    Rostyslav Dzinko over 11 years
    @D.Shawley, will agree with you here. The word "limitation" was born in my mind due to long-term communication with Ruby-guys and in Ruby everything is an expression).
  • Martijn Pieters
    Martijn Pieters over 11 years
    @user1656850: the code in the answer as it stands now increments i, then does the test. It's functionally the same.
  • boardrider
    boardrider over 11 years
    Thanks for the answers. However, two problems: A for loop is good if the number of iteration is known in advance, so it may apply in my example, but not in all cases (whereas a while loop can be applied in all cases). The solution you give will not increment the i on the last test (as the loop body will not be entered into), whereas the Java code will increment the i on the last check (because the ++i is done prior to the check).
  • yantrab
    yantrab over 11 years
    @user1656850: your analysis of the example is wrong. The Python while loop here will produce the same results as your Java code.
  • boardrider
    boardrider over 11 years
    Ned, in the Java case, when a[X] >= V, the i will be one greater than in the Python case.
  • yantrab
    yantrab over 11 years
    @user1656850: In the java case, the i is pre-incremented, so if the test fails, it will be because a[i] >= v. The same is true of the Python code. When the loop ends due to finding an element >= v, the value of i after the loop will be the index of the offending element.