4

I've been looking for the best way to iterate through a deque while using popleft to use the first element and reduce the queue for each iteration. I essentially want to popleft the first in the deque, run some code using this value and then do the same process until there are no more values left in the deque.

The best I've found online is using a try and catch block to capture an IndexError:

try: 
    while mydeque: 
        value = mydeque.popleft()
except IndexError: 
# handle empty mydeque

Surely throwing an exception isn't the best way to do this. I'd be catching any IndexError occurring in the while loop as well, which isn't ideal. Using a for loop doesn't work as I'd be modifying the deque during the iteration.

What's the best way to do this?

dandev91
  • 1,691
  • 3
  • 22
  • 34
  • 3
    What IndexError? The `while` loop ends when you run out of elements. – user2357112 Dec 31 '18 at 07:34
  • if `mydeque` is falsy when empty, no need. But if it isn't shouldn't the test be something else that is false when `mydeque` is empty. – Dan D. Dec 31 '18 at 07:35
  • I've clearly got another issue in my code somewhere. Thanks for the incredibly prompt replies. – dandev91 Dec 31 '18 at 07:37
  • 1
    The exception will never be raised by `popleft` because of the condition check: if the deque is empty, the loop ends . – DYZ Dec 31 '18 at 07:38

3 Answers3

6

When mydeque is empty, it resolves as False in the while loop.

while mydeque:
    value = mydeque.popleft()

This will run through all values in mydeque.

Stabledog
  • 3,110
  • 2
  • 32
  • 43
slightlynybbled
  • 2,408
  • 2
  • 20
  • 38
  • 1
    Deques do not have a `pop` method that takes an integer. [They *do* have a popleft, though.](https://docs.python.org/3/library/collections.html#collections.deque.popleft) – user2357112 Dec 31 '18 at 07:39
  • The difference between `pop()` and `popleft()` is from which side of the deque is the returned element. `deque.pop()` remove and return an element from the right side of the deque. `deque.popleft()` remove and return an element from the left side of the deque. In both cases if no elements are present, raises an IndexError. – buran Dec 31 '18 at 07:42
  • @user2357112, neither `pop()`, nor `popleft()` takes an integer as argument (pop is just above the popleft in the docs link you shared). @slightlynybbled, I think you confuse them with `rotate(n)`, where n is the number of steps and the sign (positive or negative number) is the direction of rotation. – buran Dec 31 '18 at 07:45
  • @buran: Yes, I am aware popleft doesn't take an integer. I did not say it takes an integer. I think it's more likely that slightlynybbled got things mixed up with lists than that they got things mixed up with `rotate`; lists have a `pop` that optionally takes an integer, and no `popleft`. – user2357112 Dec 31 '18 at 07:54
  • @user2357112, sorry, I misunderstood your comment. And yes, you are right - slightlynybbled may have mixed deque with list. – buran Dec 31 '18 at 08:02
3

You can either use while mydeque:... as @slightlynybbled suggested or while 0 < len(mydeque):... what is basically the same.

while 0 < len(mydeque):
    value = mydeque.popleft()
Kami Kaze
  • 611
  • 3
  • 14
0

You can put the try/except within the while loop; that way you can make sure it only catches the IndexError thrown by popleft

https://pymotw.com/2/collections/deque.html

while True:
  try:
    print d.popleft()
  except IndexError:
    break
michel-slm
  • 9,438
  • 3
  • 32
  • 31
  • It would be simpler and more efficient to just use the truth value of the deque object. – user2357112 Dec 31 '18 at 07:41
  • @user2357112 actually I think the code in this answer would be more efficient - it does not have to check the truth value of the deque instance every loop of the while – Anentropic Aug 16 '19 at 16:49