Reputation: 472
I am trying to write a function that removes all pdf files from a linked list, however after running this, I quickly realized that it became an infinite loop. My first while loop is supposed to catch all pdf files at the beginning of the linked list. My second while loop is supposed to iterate through the linked list as many times as it takes to get rid of the pdf files. I guess my logic for while not loops is incorrect.
def remove_all(lst):
ptr = lst
while ptr['data'][0] == 'pdf':
ptr = ptr['next']
lst = ptr
all_removed = True
while not all_removed:
all_removed = False
while ptr['next'] != None:
if ptr['next']['data'][0] == 'pdf':
ptr['next'] = ptr['next']['next']
all_removed = True
ptr = ptr['next']
return lst
I am getting the error that none type is not subscriptable for the the second while loop, which confuses me since it is supposed to stop when ptr['next'] is None.
My linked list looks like this:
{'data': ['pdf', 2, 4], 'next': {'data': ['csv', 1, 1], 'next': {'data': ['pdf', 234, 53], 'next':
{'data': ['xml', 1, 2], 'next': {'data': ['pdf', 0, 1], 'next': None}}}}}
Upvotes: 1
Views: 652
Reputation: 21
6 years later, but you got me interested. Here I present a solution to simplify complexity and a linked-list generator for testing purposes. But I don't adress the infinity loop, as I'm focusing on the first while loop of DrJessop:
The way I see it, the first while loop only "erases" consecutive pdfs at the start. But I see more potential for it as the condition is cristal clear:
Following up you find some changes:
lst['next'] != None
. Mind that the loop only stops, if the last node is linked to a None
type and the loop misses the last node.['data'][0] == 'pdf'
got moved into the while loop as an if condition. This allows to ignore all pdfs not just the ones at the start.final_ll
and a temporary linked-list temp_ll
as dictionaries, to store the relevant documents alog the iterations. These are used in the else-case:def remove_all(lst):
# initiating final ll and temporary LL for single nodes to be stored
final_ll = {}
temp_ll = final_ll # a link for temp_ll to store final results in final_ll
while lst['next'] != None: # running through all but the last node
if lst['data'][0] == 'pdf': # ignoring all pdfs
lst = lst['next'] # jump to next node
else: # including desired nodes
temp_ll['data'] = lst['data'] # add node data
temp_ll['next'] = {} # add node link
temp_ll = temp_ll['next'] # update temp_ll
lst = lst['next'] # jump to next node
# catching the last node
temp_ll['data'] = lst['data']
temp_ll['next'] = None
return final_ll
For testing purposes here is an random generator of linked lists containig documents and in the format you displayed:
from random import randint as r_
documents = ['pdf', 'xml', 'csv', 'json', 'html']
def prod_doc_ll_list(size = 3):
ll_docs = {}
ll_doc = ll_docs
for i in range(size):
ll_doc['data'] = [documents[r_(0,4)], r_(0,250), r_(0,250)]
if i < size-1:
ll_doc['next'] = {}
ll_doc = ll_doc['next']
else:
ll_doc['next'] = None
return ll_docs
docs = prod_doc_ll_list(8)
docs
Upvotes: 0
Reputation: 472
Given that I do not fully understand while not, while true loops, I resorted to recursion to answer my question.
def remove(lst):
ptr=lst
while ptr['data'][0]=='pdf':
ptr=ptr['next']
lst=ptr
while ptr['next']!=None:
if ptr['next']['data'][0]=='pdf':
ptr['next']=ptr['next']['next']
return remove(lst)
ptr=ptr['next']
return lst
If there are any pdf's at the start of the list, they are removed, and then if there are any pdf's encountered later, they are removed and the function returns itself just in case there are adjacent pdf's.
Upvotes: 0
Reputation: 53535
First, try:
ptr['next'] = ptr['next']['next']
instead of:
ptr['next'] == ptr['next']['next']
Second, since we have a 'next':
{'data': ['xml', 1, 2]
in your structure (with xml
and csv
- not pdf
), the execution goes into the nested while loop:
while ptr['next'] != None:
and since the if condition if ptr['next']['data'][0] == 'pdf':
evaluates to False
it gets stuck in the loop infinitely.
Upvotes: 1