Easiest way to include a stop parameter in enumerate python?
Asked Answered
S

4

14

Ss there a simple way to iterate over an iterable object that allows the specification of an end point, say -1, as well as the start point in enumerate. e.g.

for i, row in enumerate(myiterable, start=2): # will start indexing at 2

So if my object has a length of 10, what is the simplest way to to get it to start iterating at index 2 and stop iterating at index 9?

Alternatively, is there something from itertools that is more suitable for this. I am specifically interested in high performance methods.

In addition, when the start option was introduced in 2.6, is there any reason why a stop option was not?

Cheers

Sour answered 11/2, 2014 at 0:7 Comment(0)
L
17
for i, row in enumerate(myiterable[2:], start=2):
   if i>= limit: break
   ...

or

for i,row in itertools.takewhile(lambda (i,val):i < limit,enumerate(myiterable[2:],2)):

to rephrase the other suggestion (note that it will only work if your iterable is a sliceable object)

start,stop = 11,20
my_items = range(100)
for i,row in enumerate(my_items[start:stop],start):
      ....
Lovato answered 11/2, 2014 at 0:10 Comment(2)
thanks @ Joran Beasley, both are good options, very helpful. I know the obvious response is to the next question is benchmark it yourself, but do you have any inkling if one method you think would be faster than the other? or more preferred with large or small objects etc.?Sour
they both short curcuit so they should be equal in terms of execution ... or close to it ...Lovato
R
19

I think you've misunderstood the 'start' keyword, it doesn't skip to the nth item in the iterable, it starts counting at n, for example:

for i, c in enumerate(['a', 'b', 'c'], start=5):
    print i, c

gives:

5 a
6 b
7 c

For simple iterables like lists and tuples the simplest and fastest method is going to be something like:

obj = range(100)
start = 11
stop = 22
for i, item in enumerate(obj[start:stop], start=start):
    pass
Rockel answered 11/2, 2014 at 0:20 Comment(2)
i understand what it does. i.e iterating over a list of 0-9 starting at 2 will print up to i = 11, c = 9. maybe i phrased the question wrongly. well pointed out though.Sour
This seems to be the correct answer thenRositaroskes
L
17
for i, row in enumerate(myiterable[2:], start=2):
   if i>= limit: break
   ...

or

for i,row in itertools.takewhile(lambda (i,val):i < limit,enumerate(myiterable[2:],2)):

to rephrase the other suggestion (note that it will only work if your iterable is a sliceable object)

start,stop = 11,20
my_items = range(100)
for i,row in enumerate(my_items[start:stop],start):
      ....
Lovato answered 11/2, 2014 at 0:10 Comment(2)
thanks @ Joran Beasley, both are good options, very helpful. I know the obvious response is to the next question is benchmark it yourself, but do you have any inkling if one method you think would be faster than the other? or more preferred with large or small objects etc.?Sour
they both short curcuit so they should be equal in terms of execution ... or close to it ...Lovato
C
1

If I'm not going to be using the whole length of the iterable item, I find it easier to use something like:

for i in range(2, len(myiterable)):

instead of enumerate. And then index based on i within the loop. It requires less typing than other approaches that use enumerate.

Cuisse answered 19/3, 2021 at 18:25 Comment(0)
D
1

Creating the slice of an iterable object could be expensive. To avoid this, use itertools.islice:

import itertools

for item in itertools.islice('abc', 0, 2):
  print(item)

# will print:
1
2
Donell answered 22/1, 2022 at 11:3 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.