Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

linked list iterator python

I want to write a function called print_iterator_explicit() which prints all of the items in a linked list by making use of the Iterator. However, you are not permitted to use the standard "for ... in" loop syntax - instead you must create the Iterator object explicitly, and print each item by calling the next() method

Use the iter() and next() methods in your function definition - and remember to handle the StopIteration exception!

Below is what I've tried, but the print_iterator_explicit seems to have some problem which I can only print the first element but not the whole list.

class LinkedListIterator:

def __init__(self, head):
    self.current = head

def __next__(self):
    if self.current == None:
        raise StopIteration
    else:
        item = self.current.get_data()
        self.current = self.current.get_next()
        return item

class LinkedList:

def __init__(self):
    self.head = None

def __iter__(self):
    return LinkedListIterator(self.head)

def add(self, item): 
    new_node = Node(item)
    new_node.set_next(self.head)
    self.head = new_node

def print_iterator_explicit(items):
    it = items.__iter__()
    print(it.__next__())
like image 681
yoman Avatar asked Jun 11 '26 00:06

yoman


2 Answers

Just as mentioned by @abarnert , you always need a __iter__ method for the iterator class.

class LinkedListIterator:
    def __init__(self, head):
        self.current = head

    def __iter__(self):
        return self

    def __next__(self):
        if not self.current:
            raise StopIteration
        else:
            item = self.current.get_data()
            self.current = self.current.get_next()
            return item

class LinkedList:
    def __init__(self):
        self.head = None

    def __iter__(self):
        return LinkedListIterator(self.head)

    def add(self, item): 
        new_node = Node(item)
        new_node.set_next(self.head)
        self.head = new_node

Now that your class is iterable, you can use "for...in" loop:

test_list = LinkedList()
test_list.add(1)
test_list.add(2)
test_list.add(3)
for item in test_list:
    print(item)

Please check the tutorial here.

like image 132
ssword Avatar answered Jun 13 '26 18:06

ssword


You can use the yield keyword to make a generator so you dont have to implement __next__()

class LinkedList:
    def __init__(self):
        self.head = None

    def __iter__(self):
        curNode = self.head
        while curNode:
            yield curNode.value
            curNode = curNode.nextNode

    def add(self, item): 
        new_node = Node(item)
        new_node.set_next(self.head)
        self.head = new_node

And in your print_iterator_explicit function you can do it like this

def print_iterator_explicit(items):       
    iterator = iter(ll)
    while True:
        try:
            print(next(iterator))
        except StopIteration:
            break

Check out this link for more information on iterators and generators: Iterators and generators

A little side note: your head variable is behaving like a tail. In a linked list the first node is called the head and the last is called the tail

like image 41
Henrik Melfald Kittang Avatar answered Jun 13 '26 16:06

Henrik Melfald Kittang



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!