-1

I have created a python class for doubly linked list. It looks like this:

from tabulate import tabulate


class Node:
    def __init__(self, value):
        self.data = value
        self.next = None  # Next Node's address
        self.prev = None  # Previous Node's address


class DoublyLinkedList:
    def __init__(self):
        self.head = None  # Empty linked list
        self.tail = None  # Last node in the list
        self.n = 0  # Number of nodes

    def __len__(self):
        return self.n

    def __str__(self):
        curr = self.head
        var = ''
        while curr is not None:
            var += ', '
            var += str(curr.data)
            curr = curr.next

        return 'DLL [' + var[2:] + ']'

    def print_structure(self):
        curr = self.head
        table = []
        while curr is not None:
            table.append([hex(id(curr.prev)) if not curr.prev is None else 'None, Head', curr.data,
                          hex(id(curr.next)) if not curr.next is None else 'None, Tail'])
            curr = curr.next

        print(tabulate(table, headers=['Prev Address', 'Data', 'Next Address'], tablefmt='psql'))

    def insert_from_head(self, value):
        new_node = Node(value)
        new_node.next = self.head
        if self.head is not None:
            self.head.prev = new_node
        self.head = new_node
        if self.tail is None:
            self.tail = new_node
        self.n += 1

    def append(self, value):
        if self.head is None:
            self.head = Node(value)
            self.tail = self.head
        else:
            new_node = Node(value)
            new_node.prev = self.tail
            self.tail.next = new_node
            self.tail = new_node
        self.n += 1

    def insert(self, index, value):
        if self.head is None:
            if index != 0:
                raise IndexError('Linked List index out of range')
            else:
                self.head = Node(value)
                self.tail = self.head
                self.n += 1
        else:
            try:
                new_node = Node(value)
                curr = self.head
                for i in range(index - 1):
                    curr = curr.next
                new_node.next = curr.next
                if curr.next is not None:
                    curr.next.prev = new_node
                curr.next = new_node
                new_node.prev = curr
                if curr == self.tail:
                    self.tail = new_node
                self.n += 1
            except AttributeError:
                raise IndexError('Linked List index out of range')

    def clear(self):
        self.head = None
        self.tail = None
        self.n = 0

    def delete_head(self):
        if self.head:
            self.head = self.head.next
            if self.head is not None:
                self.head.prev = None
            else:
                self.tail = None
            self.n -= 1
        else:
            raise IndexError('list assignment index out of range')

    def pop(self):
        if self.head is None:
            raise IndexError('list assignment index out of range')
        curr = self.head
        if curr.next is None:
            self.delete_head()
            return
        while curr.next.next is not None:
            curr = curr.next
        curr.next = None
        self.tail = curr
        self.n -= 1

    def remove(self, value):
        if self.head.data == value:
            self.delete_head()
            return

        curr = self.head
        while curr.next is not None:
            if curr.next.data == value:
                break
            curr = curr.next

        if curr.next is None:
            raise ValueError(value + ' not in linked list')

        curr.next = curr.next.next
        if curr.next is not None:
            curr.next.prev = curr
        else:
            self.tail = curr
        self.n -= 1

    def __delitem__(self, index):
        if index == 0:
            self.delete_head()
            return
        if index == self.n - 1:
            self.pop()
            return

        curr = self.head
        for i in range(index):
            curr = curr.next

        if curr is None:
            raise IndexError('linked list assignment index out of range')

        if curr.next is not None:
            curr = curr.next

    def __getitem__(self, index):
        if not (0 <= index < self.n):
            raise IndexError('list index out of range')

        curr = self.head
        for i in range(index):
            curr = curr.next

        return curr.data

    def index(self, value):
        curr = self.head
        index = 0
        while curr is not None:
            if curr.data == value:
                return index
            curr = curr.next
            index += 1

        raise ValueError(f'{value} not in linked list')

    def extend_array(self, array):
        for i in array:
            self.append(i)
        

I want to implement List Comprehensions and For In loops in this.

Lets say I have added these elements to the dll like this:

dll = DoublyLinkedList()
dll.extend_array([23, 41, 56, 85, 26, 63, 17, 2, 9, 8, 34, 238])

Now How do I make it so that these two pieces of code results in this output

for i in dll:
    print(i, sep=', ')

OUTPUT:

23, 41, 56, 85, 26, 63, 17, 2, 9, 8, 34, 238

List Comprehension

arr = [i for i in dll]
print(arr)

OUTPUT:

[23, 41, 56, 85, 26, 63, 17, 2, 9, 8, 34, 238]

1 Answers1

0

Ok, nevermind, my problem is solved, just had to add these two function

def __iter__(self):
    self.current = self.head
    return self

def __next__(self):
    if self.current is None:
        raise StopIteration
    else:
        data = self.current.data
        self.current = self.current.next
        return data