list

package
v0.0.0-...-276738e Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 7, 2025 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

Package list reimplements the double linked list of Go's standard library using generics. It's API compatible with the original list.List and list.Element and it also has some extra quality of life methods (eg: 2 iterators). Using a generic type T instead of the type any avoids unconvinient type casts every time an element from the list is retrieved.

Why?

I needed a linked list for another project and the implementation in Go standard library holds values of type any. This means any time I'm traversing the list I have to type cast each node when retrieved. This was the only way of implementing a list before addition of generics. I find far more convenient if this data structures held values of a generic type instead of type any but I guess this part of the standard library is not relevant enough to receive an update. So, since I needed it I did it myself.

API Compatible

Both List[T] and Element[T] implement the same methods with an almost identical type signature (replacing type any with the generic T). Thus, 99.9% of the Go code that uses container/list types is reusable. The only exception is the list.New() func. It creates and returns a new empty list, with this implementation it's required to declare which type will T adopt.

// Standard library implementation
l := list.New()
// Own implementation
l := list.New[string]()

Since it's impossible to reimplement the list in a way where this function call didn't need to be changed I took the opportunity to add the possibility of initializing a list with some elements. The original New() func takes no args but this implentation takes a variadic number of args of type T:

// Initialize an empty list.
l := list.New[string]()

// Initialize a list with some elements, notice that in this case it's not necessary to specify
// the string type since it's inferred from the args.
l := list.New("A", "B", "C")

Extra methods

Apart from the methods of the standard library version, these other ones were created to add some quality of life improvements:

// Regular iterator:
for i := range list.Iterator() {
	fmt.Println(i) // i is of type T
}

// Backwards iterator, useful to traverse a regular list as a FILO data structure:
for i := range list.BackwardsIterator() {
	fmt.Println(i) // i is of type T
}

// Get a slice of type T holding a copy af all list elements:
s := list.ToSlice()

// Finally, both List and Element types have a string representation:
listRep := list.String()
elemRep := elem.String()

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Element

type Element[T any] struct {
	Value T
	// contains filtered or unexported fields
}

Element is an element of a linked list.

func (*Element[T]) Next

func (e *Element[T]) Next() *Element[T]

Next returns the next list element or nil.

func (*Element[T]) Prev

func (e *Element[T]) Prev() *Element[T]

Prev returns the previous list element or nil.

func (*Element[T]) String

func (e *Element[T]) String() string

String returns a string representation of the list node

type List

type List[T any] struct {
	// contains filtered or unexported fields
}

List represents a doubly linked list. The zero value for List is an empty list ready to use.

func New

func New[T any](elements ...T) *List[T]

New returns an initialized list either empty or with some elements.

func (*List[T]) Back

func (l *List[T]) Back() *Element[T]

Back returns the last element of list l or nil if the list is empty.

func (List[T]) BackwardsIterator

func (l List[T]) BackwardsIterator() iter.Seq[T]

BackwardsIterator returns an iterator that traverses all list elements from last to first that can be used in the for loop.

Example
package main

import (
	"fmt"

	"github.com/n-mou/yagul/list"
)

func main() {
	l := list.New("A", "B", "C", "D")
	for i := range l.BackwardsIterator() {
		fmt.Println(i)
	}
}
Output:

D
C
B
A

func (*List[T]) Front

func (l *List[T]) Front() *Element[T]

Front returns the first element of list l or nil if the list is empty.

func (*List[T]) Init

func (l *List[T]) Init() *List[T]

Init initializes or clears list l.

func (*List[T]) InsertAfter

func (l *List[T]) InsertAfter(v T, mark *Element[T]) *Element[T]

InsertAfter inserts a new element e with value v immediately after mark and returns e. If mark is not an element of l, the list is not modified. The mark must not be nil.

func (*List[T]) InsertBefore

func (l *List[T]) InsertBefore(v T, mark *Element[T]) *Element[T]

InsertBefore inserts a new element e with value v immediately before mark and returns e. If mark is not an element of l, the list is not modified. The mark must not be nil.

func (List[T]) Iterator

func (l List[T]) Iterator() iter.Seq[T]

Iterator returns an iterator that traverses all list elements from first to last that can be used in the for loop.

Example
package main

import (
	"fmt"

	"github.com/n-mou/yagul/list"
)

func main() {
	l := list.New("A", "B", "C", "D")
	for i := range l.Iterator() {
		fmt.Println(i)
	}
}
Output:

A
B
C
D

func (*List[T]) Len

func (l *List[T]) Len() int

Len returns the number of elements of list l. The complexity is O(1).

func (*List[T]) MoveAfter

func (l *List[T]) MoveAfter(e, mark *Element[T])

MoveAfter moves element e to its new position after mark. If e or mark is not an element of l, or e == mark, the list is not modified. The element and mark must not be nil.

func (*List[T]) MoveBefore

func (l *List[T]) MoveBefore(e, mark *Element[T])

MoveBefore moves element e to its new position before mark. If e or mark is not an element of l, or e == mark, the list is not modified. The element and mark must not be nil.

func (*List[T]) MoveToBack

func (l *List[T]) MoveToBack(e *Element[T])

MoveToBack moves element e to the back of list l. If e is not an element of l, the list is not modified. The element must not be nil.

func (*List[T]) MoveToFront

func (l *List[T]) MoveToFront(e *Element[T])

MoveToFront moves element e to the front of list l. If e is not an element of l, the list is not modified. The element must not be nil.

func (*List[T]) PushBack

func (l *List[T]) PushBack(v T) *Element[T]

PushFront inserts a new element e with value v at the front of list l and returns e.

func (*List[T]) PushBackList

func (l *List[T]) PushBackList(other *List[T])

PushBackList inserts a copy of another list at the back of list l. The lists l and other may be the same. They must not be nil.

func (*List[T]) PushFront

func (l *List[T]) PushFront(v T) *Element[T]

PushFront inserts a new element e with value v at the front of list l and returns e.

func (*List[T]) PushFrontList

func (l *List[T]) PushFrontList(other *List[T])

PushFrontList inserts a copy of another list at the front of list l. The lists l and other may be the same. They must not be nil.

func (*List[T]) Remove

func (l *List[T]) Remove(e *Element[T]) T

Remove removes e from l if e is an element of list l. It returns the element value e.Value. The element must not be nil.

func (List[T]) String

func (l List[T]) String() string

String returns a string representation of the list and all it's members.

func (List[T]) ToSlice

func (l List[T]) ToSlice() []T

ToSlice returns a slice with a copy of the elements present in the list.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL