Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Python decreasing for loop

Tags:

python

Imitating an "increasing" C-styled for loop in Python is very simple:

for (int i = A ; i < B ; i += C)

can be easily implemented in Python, Without consuming memory for an array from A to B, using:

for i in range(A, B, C)    # (xrange if Python 2.x)

But what about decreasing loops?

How can one imitate C-styled loops such as:

for (int i = A ; i >= B ; i -= C)

Even using reversed(range(A, B, C)) constructs an array in the memory, as reversed first has to evaluate the whole range generator in order to yield its values reversed...

Is there any trick for implementing such a for loop in Python, without constructing an array in the memory? Is there an equivalent for range generator, that yields decreasing numbers?

like image 990
Chur7U Avatar asked Oct 20 '25 14:10

Chur7U


2 Answers

range takes 3 args range(start,stop,step). The step arg can be negative to iterate backwards.

arr = range(10) # range generator in python 3
for i in range(len(arr)-1,0,-1):
    print(arr[i])
9
8
7
6
5
4
3
2
1

Note that the start is len(arr)-1 because lists are 0-indexed so the max idx is 9 for a list of length 10.

Negative steps don't have to be 1 either:

for i in range(len(arr)-1,0,-3):
    print(arr[i])    
9
6
3

In answer to your second question, you can set arr to be a countdown from the beginning

arr = range(10,0,-1)
for a in arr: print(a)

10
9
8
7
6
5
4
3
2
1
like image 104
RSHAP Avatar answered Oct 22 '25 05:10

RSHAP


Just go ahead and call reversed() on the result of range(). It won't build the whole list because the range object has a __reversed__ method, which the reversed() function detects and uses. Here's how you can see that it has that method:

>>> dir(range(3))
['__class__', '__contains__', '__delattr__', '__dir__', '__doc__', '__eq__', '__format__', '__ge__', '__getattribute__', '__getitem__', '__gt__', '__hash__', '__init__', '__iter__', '__le__', '__len__', '__lt__', '__ne__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__reversed__', '__setattr__', '__sizeof__', '__str__', '__subclasshook__', 'count', 'index', 'start', 'step', 'stop']

This is assuming you're using Python 3. In Python 2, range builds a list in memory regardless of whether you reverse it, although most of the time it makes no performance difference. You can use xrange, which is like Python 3's range, and also has a __reversed__ method.

like image 29
Arthur Tacca Avatar answered Oct 22 '25 04:10

Arthur Tacca