2

I'm having a problem trying to extract elements from a queue until a given number. If the given number is not queued, the code should leave the queue empty and give a message saying that.

Instead, I get this error message, but I'm not able to solve it:

Traceback (most recent call last):
  File "python", line 45, in <module>
IndexError: list index out of range

This is my current code:

class Queue():
  def __init__(self):
      self.items = []
  def empty(self):
    if self.items == []:
      return True
    else:
      return False
  def insert(self, value):
        self.items.append(value)
  def extract(self):
    try:
      return self.items.pop(0)
    except:
      raise ValueError("Empty queue")
  def last(self):
    if self.empty():
      return None
    else:
      return self.items[0]

import random
def randomlist(n2,a2,b2):
    list = [0]  * n2
    for i in range(n2):
      list[i] = random.randint(a2,b2)
    return list

queue1=Queue()
for i in range (0,10):
  queue1.insert(randomlist(10,1,70)[i])
if queue1.empty()==False :
  print("These are the numbers of your queue:\n",queue1.items)

test1=True
while test1==True:
  s=(input("Input a number:\n"))
  if s.isdigit()==True :
   test1=False
   s2=int(s)
  else:
    print("Wrong, try again\n")

for i in range (0,10) :    
  if queue1.items[i]!=s2 :
    queue1.extract()
  elif queue1.items[i]==s2 :
    queue1.extract()
    print ("Remaining numbers:\n",queue1.items)
    break
if queue1.empty()==True :
  print ("Queue is empty now", cola1.items)
3
  • Let me explain myself... Imagine this example These are the numbers of your queue: [30, 7, 19, 62, 41, 1, 3, 35, 16, 46] Input a number: 7 So the result should be: Remaining numbers: [19, 62, 41, 1, 3, 35, 16, 46] Commented Jan 27, 2018 at 15:21
  • your def randomlist(n2,a2,b2) is list(random.choices(range(a2,b2+1),k=n2) Commented Jan 27, 2018 at 15:28
  • 1
    you should never use list, dict or any other reserved word as variablename - your variable is shadowing the inbuild type and you run into problems. Commented Jan 27, 2018 at 15:34

4 Answers 4

1

extract elements from a queue until a given number. If the given number is not queued, the code should leave the queue empty and give a message saying that.

while not queue.empty():
    if queue.extract() == target:
        print('Found! Remaining numbers:', queue.items)
        break
else:
    print('Not found! Remaining numbers:', queue.items)
Sign up to request clarification or add additional context in comments.

Comments

1

Modifying a list while going through it is a bad idea.

 for i in range (0,10) :    
    if queue1.items[i]!=s2 :
        queue1.extract()
    elif queue1.items[i]==s2 :
        queue1.extract()
        print ("Remaining numbers:\n",queue1.items)

This code modifies your queue - items, it shortens the items-list but you still itereate over the full range if no items is found. So your internal list will get shorter and shorter and your range (i) advances towards i.

Somewhen you access an items[i] that is no longer in your queue.

Solution (Edited thanks to Stefan Pochmann's comment):

 for _ in range(len(queue1.items)):    # no hardcoded length anymore
    item = queue1.extract()              # pop item
    if item == s2 :                      # check item for break criteria
        print ("Remaining numbers:\n",queue1.items)
        break

3 Comments

@StefanPochmann I am just reusing his Queue class. He is discarding the values from the queue until the number is found, discards the found number and prints the remaining ones. After looking I found what you ment, thanks for pointing it out. I still feel better with the range() though, as I am modifying the internal item list and using for _ in queue1.items: looks dangerous to me that way
Ha, didn't want to wait longer, posted my answer and was going to remove my comments but seconds later you updated :-). Oh well, we're still a bit different.
Right, I think ideally we shouldn't directly use the queue's internal items from the outside at all. That's one reason I prefer "while not empty" over that range. I'm still touching items it as well, but I guess that's only for debug-printing to check that all is well. Anyway, I'd say your updated version is much improved and you explain their failure (I just can't be bothered to explain that yet again), so +1 as well :-)
0

You can try replacing the last part of your code i.e.

for i in range (0,10) :    
  if queue1.items[i]!=s2 :
    queue1.extract()
  elif queue1.items[i]==s2 :
    queue1.extract()
    print ("Remaining numbers:\n",queue1.items)
    break
if queue1.empty()==True :
  print ("Queue is empty now", cola1.items)

with

poptill = -1 # index till where we should pop
for i in range(0,len(queue1.items)): # this loop finds the index to pop queue till
  if queue1.items[i]==s2:
    poptill = i
    break

if poptill != -1: # if item to pop was found in queue
  i = 0
  while i <= poptill: # this loop empties the queue till that index
    queue1.extract()
    i += 1
  if queue1.empty()==True :
    print ("Queue is empty now", queue1.items)
  else:
    print ("Remaining numbers:\n",queue1.items)
else: # else item was not found in list
  for i in range(0,len(queue1.items)): # this loop empties the queue
    queue1.extract()
  print ("no item found, so emptied the list, numbers:\n",queue1.items)

Here we find the index location till where we should pop in the first loop, and then pop the queue till that index in the second loop, finally if the item to pop was not found in list we empty list in the third loop.

3 Comments

Thanks a lot, Faraz. Anyway, if the given number is not in the queue, the code doesn't extrat any item, how can I solve that?
I edited, to empty the list if no item is found you can write code to empty the list in your queue class and call it in final else or write the code to empty itself in the final else. Is it clear?
Now emptying the list if item was not found.
0

The test code operates from 0 to 10, but when you extract an element, that decreases the size of the queue.

So if the queue is originally 10 element long, the index i you provide will eventually be >= the length of the queue.

Hence an IndexError.

Try one of the other suggested code segments.

1 Comment

Understood. Thanks!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.