boardrider
boardrider

Reputation: 6185

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

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.

Upvotes: 4

Views: 48604

Answers (4)

user68014
user68014

Reputation: 146

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

Upvotes: 2

Karl Knechtel
Karl Knechtel

Reputation: 61498

The list class has a built-in method that does this kind of searching, but for whatever reason it only compares for equality. Of course, we can hack that:

class hax:
  def __init__(self, value): self.value = value
  def __eq__(self, other): return other >= self.value

a.index(hax(a[lo]), lo + 1, hi + 1)

... but please don't :)

Anyway, not only should you not be trying to port the code directly, as @Rostyslav suggests - you shouldn't really be trying to port the problem directly. There's something very strange about a Python program that uses lists in a way that would allow a problem like this to come up.

Upvotes: 0

Ned Batchelder
Ned Batchelder

Reputation: 375494

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

Upvotes: 4

Rostyslav Dzinko
Rostyslav Dzinko

Reputation: 40755

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.

Upvotes: 10

Related Questions