xlist

package module
v1.2.1 Latest Latest
Warning

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

Go to latest
Published: Feb 14, 2026 License: MIT Imports: 10 Imported by: 0

README

XList is a classic two-linked list

Introduction

XList is a generic, thread-safe, doubly-linked list for Go. It's a high-performance alternative to slices, optimized for frequent insertions, deletions, and reordering. The API design is inspired by the power and simplicity of NSArray from Apple's Cocoa framework.

Key features include:

  • Rich Core API: Full CRUD, unique element handling, and list-splicing operations.
  • Bulk & Batch Processing: Find, Modify, and ModifyRev using closures.
  • Concurrent Sorting: Fast, stable, in-place merge sort.
  • Dual Iterator Models:
    • Classic stateful iterator for manual control (Next/Prev).
    • Modern range iterators for Go 1.23+ with Filter, Map, etc.
  • Element Marking: Built-in flags for complex selection logic.
  • Go Integration: Easily convert to a standard slice via Slice().

Installation and usage

Install go module:

go get github.com/DmitryVokhmin/xlist

Functionality overview

This section provides a brief overview of the library's functionality.

Core Functions
  • New: Creates a new empty XList container.
  • At: Returns the value at the specified index.
  • AtPtr: Returns a pointer to the value at the specified index.
  • IsEmpty: Checks if the container is empty.
  • Size: Returns the number of elements in the container.
  • LastObject: Returns the last element in the container.
  • LastObjectPtr: Returns a pointer to the last element in the container.
  • Clear: Removes all elements from the container.
  • Set: Replaces the container's contents with a new set of objects.
  • Append: Adds objects to the end of the container.
  • AppendUnique: Appends elements if they don't already exist in the collection.
  • Contains: Checks if a set of objects is fully contained in the list.
  • ContainsSome: Checks if any of the provided objects exist in the list.
  • Insert: Inserts objects at a specified position.
  • Replace: Replaces the element at a specified position.
  • ReplaceLast: Replaces the last element.
  • DeleteAt: Deletes the element at a specified position.
  • DeleteLast: Deletes the last element.
  • AppendList: Appends another list to the end of the current list (mutating).
  • Splice: Moves all elements from another list to the end of the current list, emptying the source list.
  • SpliceAtPos: Inserts another list's content at a specified position, emptying the source list.
  • Copy: Creates a shallow copy of the list.
  • CopyRange: Creates a shallow copy of a specified range of elements.
  • DeepCopy: Creates a deep copy of the list using a provided copy function.
  • DeepCopyRange: Creates a deep copy of a specified range using a provided copy function.
  • Swap: Swaps two elements in the list.
Bulk Processing
  • Find: Returns a new list containing elements that match the given predicate.
  • Modify: Modifies each element in the collection using a provided function.
  • ModifyRev: Modifies each element in reverse order.
Sorting
  • Sort: Sorts the list using a stable, concurrent merge sort algorithm based on the provided comparison function.
  • ScanSort: An alias for Sort.
Iterators
  • Iterator: Creates a classic iterator for sequential processing over a specified range.
  • Reset: Resets the iterator with a new range.
  • SetIndex: Sets the iterator to a specific index.
  • SetFirst: Moves the iterator to the first element.
  • SetLast: Moves the iterator to the last element.
  • Index: Returns the current iterator index.
  • Value: Returns the value at the current iterator position.
  • Next: Moves the iterator to the next element.
  • Prev: Moves the iterator to the previous element.
  • NextValue: Moves to the next element and returns its value.
  • PrevValue: Moves to the previous element and returns its value.
Range Iterators (Go 1.23+)
  • All: Returns a forward range iterator over the list.
  • Backward: Returns a reverse range iterator over the list.
  • Values: Returns a forward range iterator of values only (no index).
  • ValuesBackward: Returns a reverse range iterator of values only.
  • ToValues: A helper function to transform an iterator with index and value into an iterator of values only.
  • Filter: Creates an iterator that yields only elements matching a predicate.
  • TakeWhile: Creates an iterator that yields elements as long as a predicate is true.
  • SkipWhile: Creates an iterator that skips elements while a predicate is true and then yields the rest.
  • Map: Creates an iterator that transforms each element from one type to another.
  • AnyMatch: A terminal operation that checks if any element matches a predicate.
  • AllMatch: A terminal operation that checks if all elements match a predicate.
Marking
  • MarkAtIndex: Marks an element at a specific index.
  • UnmarkAtIndex: Unmarks an element at a specific index.
  • IsMarkedAtIndex: Checks if an element at a specific index is marked.
  • MarkAll: Marks all elements in the list.
  • UnmarkAll: Unmarks all elements in thelist.
Integrations
  • Slice: Converts the list into a standard Go slice.

API description

Core Methods

New( ...T )
creates a new empty XList container
New(objects ...T) *XList[T]

Creates a new empty XList container. If initial objects are provided, they will be added to the container.

Example:

list := xlist.New[int](1, 2, 3)
fmt.Println(list.Size()) // Output: 3
At( int )
returns value at specified position
At(index int) (T, bool)

Returns the value and a bool flag: true if the value is valid, false if index is out of range. This method is recommended for value types (e.g., XList[int], XList[string]) where you need to distinguish between a valid zero value and a missing element.

Example:

list := xlist.New[int](10, 20, 30)

value, ok := list.At(1)
if ok {
    fmt.Println(value) // Output: 20
} else {
    fmt.Println("No value at this position")
}

// For value types, zero value needs explicit check
value, ok = list.At(10) // Out of range
fmt.Println(value, ok)  // Output: 0 false
AtPtr( int )
returns value at specified position (optimized for pointer types)
AtPtr(index int) T

Returns the value at the specified index, or zero value (nil for pointers) if not found. This method is designed for pointer types (e.g., XList[*User], XList[*MyStruct]) where nil naturally indicates absence - simply check if the returned pointer is nil.

For value types, use At() instead to properly distinguish zero values from missing elements.

Example:

type User struct {
    Name string
    Age  int
}

list := xlist.New[*User](
    &User{"Alice", 30},
    &User{"Bob", 25},
)

// For pointer types, nil check is natural and convenient
user := list.AtPtr(0)
if user != nil {
    fmt.Println(user.Name) // Output: Alice
}

user = list.AtPtr(10) // Out of range
if user == nil {
    fmt.Println("No user at this position") // This will print
}
IsEmpty()
Checks if the container is empty or not.
IsEmpty() bool

This function returns 'true' if container is empty

Example:

if list.IsEmpty() {
    fmt.Println("List is empty")
} else {
    fmt.Println("List is not empty")
}
Size()
returns number of elements inside container
Size() int 

Example:

fmt.Println("List size is", list.Size())
LastObject()
returns the last element in the container
LastObject() (T, bool)

Returns the last element and a bool flag: true if the value is valid, false if container is empty. This method is recommended for value types (e.g., XList[int], XList[string]) where you need to distinguish between a valid zero value and an empty container.

Example:

list := xlist.New[int](10, 20, 30)

value, ok := list.LastObject()
if ok {
    fmt.Println(value) // Output: 30
} else {
    fmt.Println("List is empty")
}

// Empty list example
emptyList := xlist.New[int]()
value, ok = emptyList.LastObject()
fmt.Println(value, ok) // Output: 0 false
LastObjectPtr()
returns the last element in the container (optimized for pointer types)
LastObjectPtr() T

Returns the last element, or zero value (nil for pointers) if container is empty. This method is designed for pointer types (e.g., XList[*User], XList[*MyStruct]) where nil naturally indicates absence - simply check if the returned pointer is nil.

For value types, use LastObject() instead to properly distinguish zero values from empty container.

Example:

type User struct {
    Name string
    Age  int
}

list := xlist.New[*User](
    &User{"Alice", 30},
    &User{"Bob", 25},
)

// For pointer types, nil check is natural and convenient
user := list.LastObjectPtr()
if user != nil {
    fmt.Println(user.Name) // Output: Bob
}

// Empty list example
emptyList := xlist.New[*User]()
user = emptyList.LastObjectPtr()
if user == nil {
    fmt.Println("List is empty") // This will print
}
Clear()
Clears container content
Clear() *XList[T]

Returns self for method chaining; return value can be ignored.

Example:

list.Clear()

// or with chaining
list.Clear().Append(1, 2, 3)
Set(...T)
set 'objects' to container
Set(objects ...T) *XList[T]

Set object to the container. In case of empty objects objects receiver will be unchanged. Returns self for method chaining; return value can be ignored.

( !!! ) It resets all the container content and removes old values. Consider using Append() if you want to keep old values

Example:

n := list.Size() // n == 2 (2 elements in container)
list.Set(1, 2, 3, 4, 5)
n := list.Size() // n == 5

// or with chaining
list.Set(1, 2, 3).Append(4, 5)
Append(...T)
appends 'objects' to container
Append(objects ...T) *XList[T]

Appends new values 'objects' to container. In case of empty objects receiver will be unchanged. Returns self for method chaining; return value can be ignored.

Example:

n := list.Size() // n == 2 (2 elements in container)
list.Append(1, 2, 3, 4, 5)
n := list.Size() // n == 7

// or with chaining
list.Append(1, 2).Append(3, 4)
AppendUnique(...T)
appends unique 'objects' to container (adds elements if they don't exist)
AppendUnique(objects ...T) *XList[T]

Adds new objects to the container but skips any that already exist within the container. Returns self for method chaining; return value can be ignored.

Example:

list.Set(1, 6)
n := list.Size() // n == 2 (2 elements in container)

list.AppendUnique(1, 2, 3, 4, 5)
n := list.Size() // n == 6
Contains(...T)
checks whether the set of objects is in the container
Contains(objects ...T) bool

Function checks whether the set of objects (the whole set) is in the container.

Example:

if list.Contains(1, 2, 3, 4, 5) {
    fmt.Println("All elements are in the container")
}
ContainsSome(...T)
checks whether any of objects is in the container
ContainsSome(objects ...T) bool

Function checks whether any of the provided objects is in the container. Returns true if at least one object is found.

Example:

list := xlist.New[int](1, 2, 3)

if list.ContainsSome(5, 6, 2) {
    fmt.Println("At least one element is in the container") // This will print
}

if !list.ContainsSome(10, 20, 30) {
    fmt.Println("None of the elements are in the container") // This will print
}
Insert(int, ...T)
inserts 'objects' at position 'pos'
Insert(pos int, objects ...T) error

Function inserts objects before the position 'pos'. If the position exceeds the container's size, objects will be appended to the end.

Example:

if err = list.Insert(8, obj1, obj2, obj3, obj4, obj5); err != nil {
	fmt.Println("Insert error: %w",err)
}
Replace(int, T)
replaces element at specified position
Replace(pos int, obj T) error

Function replaces element at position 'pos' to 'obj'. Returns an error if the position is out of the container bounds.

Example:

if err = list.Replace(8, obj); err != nil {
	fmt.Println("Replace error: %w",err)
}
ReplaceLast(T)
replaces last element in the container
ReplaceLast(obj T) error

Function replaces the last element in the container with 'obj'. Returns an error if the container is empty.

Example:

if err = list.ReplaceLast(newObj); err != nil {
    fmt.Println("ReplaceLast error:", err)
}
DeleteAt(int)
deletes element at specified position
DeleteAt(pos int) (T, error)

Function removes an element at position 'pos' and returns its value. Returns an error if the position is out of bounds or the container is empty.

Example:

value, err := list.DeleteAt(5)
if err != nil {
    fmt.Println("DeleteAt error:", err)
} else {
    fmt.Println("Deleted value:", value)
}
DeleteLast()
deletes last element from the container
DeleteLast() (T, error)

Function removes the last element from the container and returns its value. Returns an error if the container is empty.

Example:

value, err := list.DeleteLast()
if err != nil {
    fmt.Println("DeleteLast error:", err)
} else {
    fmt.Println("Last value deleted:", value)
}
AppendList( *XList[T] )
adds elements from another list to the end of this list
AppendList(dList *XList[T]) *XList[T]

Function adds copies of elements from 'dList' to the end of the receiver's list. The source list 'dList' remains unchanged. Returns self for method chaining; return value can be ignored.

Example:

list1 := xlist.New(1, 2, 3)
list2 := xlist.New(4, 5, 6)
list1.AppendList(list2)

// list1 now contains [1, 2, 3, 4, 5, 6]
// list2 remains unchanged [4, 5, 6]
Splice( *XList[T] )
moves content from another list to the end of this list
Splice(dList *XList[T]) *XList[T]

Function moves content from 'dList' to the end of the receiver. After this operation, 'dList' becomes empty. Returns self for method chaining; return value can be ignored.

Example:

list1 := xlist.New(1, 2, 3)
list2 := xlist.New(4, 5, 6)
list1.Splice(list2)

// list1 now contains [1, 2, 3, 4, 5, 6]
// list2 is now empty
SpliceAtPos( int, *XList[T] )
inserts content from another list at specified position
SpliceAtPos(pos int, dList *XList[T]) error

Function inserts (moves) content from 'dList' to receiver at position 'pos'. After this operation, 'dList' becomes empty. Returns an error if the position is out of bounds.

Example:

list1 := xlist.New(1, 2, 5, 6)
list2 := xlist.New(3, 4)

err := list1.SpliceAtPos(2, list2)
if err != nil {
    fmt.Println("SpliceAtPos error:", err)
} else {
    // list1 now contains [1, 2, 3, 4, 5, 6]
    // list2 is now empty
}
Copy()
creates a shallow copy of the list
Copy() *XList[T]

Function returns a shallow copy of the list. For deep copying, use DeepCopy() method.

Example:

list := xlist.New(1, 2, 3, 4, 5)

copyList := list.Copy()

// copyList contains [1, 2, 3, 4, 5]
// Modifying copyList doesn't affect original list
CopyRange( int, int )
creates a copy of a range of elements
CopyRange(fromPos int, toPos int) (*XList[T], error)

Creates a new container with a shallow copy of elements from position fromPos to toPos (inclusive). Returns an error if the range is invalid.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)
sublist, err := list.CopyRange(1, 3)
if err != nil {
    fmt.Println("CopyRange error:", err)
} else {
    fmt.Println(sublist.Size()) // Output: 3
    fmt.Println(sublist.AtPtr(0)) // Output: 2
    fmt.Println(sublist.AtPtr(1)) // Output: 3
    fmt.Println(sublist.AtPtr(2)) // Output: 4
}
DeepCopy( func(T) T )
creates a deep copy of the list
DeepCopy(deepCopyFn func(T) T) *XList[T]

Creates a new container with deep copies of all elements. You must provide a closure deepCopyFn that knows how to make a deep copy of type T.

Example:

type Person struct {
    Name string
    Age  int
}

list := xlist.New[*Person](
    &Person{"Alice", 30},
    &Person{"Bob", 25},
)

// Deep copy with custom copy function
copyList := list.DeepCopy(func(p *Person) *Person {
    return &Person{Name: p.Name, Age: p.Age}
})

// Modifying the copy doesn't affect the original
copyList.AtPtr(0).Name = "Charlie"
fmt.Println(list.AtPtr(0).Name)     // Output: Alice
fmt.Println(copyList.AtPtr(0).Name) // Output: Charlie
DeepCopyRange( int, int, func(T) T )
creates a deep copy of a range of elements
DeepCopyRange(fromPos int, toPos int, deepCopyFn func(T) T) (*XList[T], error)

Creates a new container with deep copies of elements from position fromPos to toPos (inclusive). You must provide a closure deepCopyFn that knows how to make a deep copy of type T. Returns an error if the range is invalid or if deepCopyFn is nil.

Example:

type Person struct {
    Name string
    Age  int
}

list := xlist.New[*Person](
    &Person{"Alice", 30},
    &Person{"Bob", 25},
    &Person{"Charlie", 35},
)

sublist, err := list.DeepCopyRange(0, 1, func(p *Person) *Person {
    return &Person{Name: p.Name, Age: p.Age}
})
if err != nil {
    fmt.Println("DeepCopyRange error:", err)
} else {
    fmt.Println(sublist.Size()) // Output: 2
}
Swap( int, int )
swaps two elements in the list
Swap(i, j int) error

Swaps two elements at positions i and j. Returns an error if either index is out of bounds.

Example:

list := xlist.New[int](1, 2, 3, 4)
err := list.Swap(1, 2)
if err != nil {
    fmt.Println("Swap error:", err)
} else {
    fmt.Println(list.AtPtr(1)) // Output: 3
    fmt.Println(list.AtPtr(2)) // Output: 2
}

Marking Methods

Container element marking methods allow working with groups of objects without implementing additional logic.

MarkAtIndex( int )
marks an element at the specified index
MarkAtIndex(index int)

Marks the element at the specified index. This can be used for custom marking logic.

Example:

list := xlist.New[int](1, 2, 3, 4)

list.MarkAtIndex(2)

fmt.Println(list.IsMarkedAtIndex(2)) // Output: true
UnmarkAtIndex( int )
unmarks an element at the specified index
UnmarkAtIndex(index int)

Clears the mark of the element at the specified index.

Example:

list := xlist.New[int](1, 2, 3, 4)

list.MarkAtIndex(2)
list.UnmarkAtIndex(2)

fmt.Println(list.IsMarkedAtIndex(2)) // Output: false
IsMarkedAtIndex(int)
checks whether an element is marked at the specified index
IsMarkedAtIndex(index int) bool

Returns true if the element at the specified index is marked, otherwise false.

Example:

list := xlist.New[int](1, 2, 3, 4)

list.MarkAtIndex(2)

fmt.Println(list.IsMarkedAtIndex(2)) // Output: true
fmt.Println(list.IsMarkedAtIndex(1)) // Output: false
MarkAll()
marks all elements in the list
MarkAll()

Marks all elements in the list.

Example:

list := xlist.New[int](1, 2, 3, 4)

list.MarkAll()

fmt.Println(list.IsMarkedAtIndex(0)) // Output: true
fmt.Println(list.IsMarkedAtIndex(1)) // Output: true
fmt.Println(list.IsMarkedAtIndex(2)) // Output: true
fmt.Println(list.IsMarkedAtIndex(3)) // Output: true
UnmarkAll()
unmarks all elements in the list
UnmarkAll()

Clears the mark of all elements in the list.

Example:

list := xlist.New[int](1, 2, 3, 4)

list.MarkAll()
list.UnmarkAll()

fmt.Println(list.IsMarkedAtIndex(0)) // Output: false
fmt.Println(list.IsMarkedAtIndex(1)) // Output: false
fmt.Println(list.IsMarkedAtIndex(2)) // Output: false
fmt.Println(list.IsMarkedAtIndex(3)) // Output: false

Integrations with Go primitives

Slice()
get a Go slice from collection
Slice() []T

Functions returns all collection objects as a slice.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

slice := list.Slice()

fmt.Println(slice) // Output: [1 2 3 4 5]

Range Iterators (Go 1.23+)

These methods leverage Go's new iter package (available from Go 1.23) to provide powerful and flexible ways to iterate over the list. They support functional programming patterns like filtering, mapping, and chaining.

All
returns a forward iterator over the list with index and value
All(opt ...func(*RangeOptions)) iter.Seq2[int, T]

Returns a forward iterator (iter.Seq2) that yields both the index and the value for each element. The iteration can be constrained using WithPos(int) to specify a starting index and WithCount(int) to limit the number of elements.

Example:

list := xlist.New[string]("a", "b", "c", "d", "e")

// Iterate over all elements
for i, v := range list.All() {
    fmt.Printf("Index: %d, Value: %s\n", i, v)
}
// Output:
// Index: 0, Value: a
// Index: 1, Value: b
// ...

// Iterate starting from index 2 with a count of 2
for i, v := range list.All(xlist.WithPos(2), xlist.WithCount(2)) {
    fmt.Printf("Index: %d, Value: %s\n", i, v)
}
// Output:
// Index: 2, Value: c
// Index: 3, Value: d
Backward
returns a reverse iterator over the list with index and value
Backward(opt ...func(*RangeOptions)) iter.Seq2[int, T]

Returns a reverse iterator that yields the index and value for each element, starting from the end of the list and moving to the beginning. It also supports WithPos and WithCount options.

Example:

list := xlist.New[string]("a", "b", "c", "d", "e")

// Iterate backward over all elements
for i, v := range list.Backward() {
    fmt.Printf("Index: %d, Value: %s\n", i, v)
}
// Output:
// Index: 4, Value: e
// Index: 3, Value: d
// ...

// Iterate backward starting from index 3 with a count of 2
for i, v := range list.Backward(xlist.WithPos(3), xlist.WithCount(2)) {
	fmt.Printf("Index: %d, Value: %s\n", i, v)
}
// Output:
// Index: 3, Value: d
// Index: 2, Value: c
Values
returns a forward iterator of values only
Values(opt ...func(*RangeOptions)) iter.Seq[T]

A convenience method that returns a forward iterator (iter.Seq) yielding only the values, without indices. It's equivalent to ToValues(list.All(...)).

Example:

list := xlist.New[int](10, 20, 30)

for v := range list.Values() {
    fmt.Println(v)
}
// Output:
// 10
// 20
// 30
ValuesBackward
returns a reverse iterator of values only
ValuesBackward(opt ...func(*RangeOptions)) iter.Seq[T]

A convenience method that returns a reverse iterator yielding only values. It's equivalent to ToValues(list.Backward(...)).

Example:

list := xlist.New[int](10, 20, 30)

for v := range list.ValuesBackward() {
    fmt.Println(v)
}
// Output:
// 30
// 20
// 10
ToValues
converts an iterator with index and value to one with values only
ToValues[T any](seq2 iter.Seq2[int, T]) iter.Seq[T]

A helper function that transforms an iter.Seq2[int, T] (yielding index and value) into an iter.Seq[T] (yielding only values).

Example:

list := xlist.New[int](1, 2, 3)
valuesIterator := xlist.ToValues(list.All())

for v := range valuesIterator {
    fmt.Println(v)
}
// Output:
// 1
// 2
// 3
Filter
creates an iterator that yields only elements matching a predicate
Filter[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

An iterator adapter that takes an iter.Seq2 and a predicate function. It returns a new iter.Seq2 that only yields elements for which the predicate returns true.

Example:

list := xlist.New[int](1, 2, 3, 4, 5, 6)
evenNumbers := xlist.Filter(list.All(), func(i int, v int) bool {
    return v%2 == 0
})

for i, v := range evenNumbers {
    fmt.Printf("Found even number at index %d: %d\n", i, v)
}
// Output:
// Found even number at index 1: 2
// Found even number at index 3: 4
// Found even number at index 5: 6
TakeWhile
creates an iterator that yields elements while a predicate is true
TakeWhile[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

An iterator adapter that yields elements from the input sequence as long as the predicate returns true. The iteration stops permanently after the first time the predicate returns false.

Example:

list := xlist.New[int](2, 4, 5, 6, 7)
initialEvens := xlist.TakeWhile(list.All(), func(_ int, v int) bool {
    return v%2 == 0
})

for _, v := range initialEvens {
    fmt.Println(v)
}
// Output:
// 2
// 4
// (Stops at 5, because it's not even)
SkipWhile
creates an iterator that skips elements while a predicate is true
SkipWhile[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

An iterator adapter that skips elements from the input sequence as long as the predicate returns true. Once the predicate returns false, it starts yielding all subsequent elements.

Example:

list := xlist.New[int](2, 4, 5, 6, 7)
tail := xlist.SkipWhile(list.All(), func(_ int, v int) bool {
    return v%2 == 0
})

for _, v := range tail {
    fmt.Println(v)
}
// Output:
// 5
// 6
// 7
// (Skips 2 and 4, starts yielding from 5)
Map
creates an iterator that transforms each element in a sequence
Map[T, V any](seq iter.Seq[T], transform func(T) V) iter.Seq[V]

An iterator adapter that applies a transform function to each element of an input iter.Seq, producing a new iter.Seq with the transformed values. Note this works on value-only iterators.

Example:

list := xlist.New[int](1, 2, 3)
asStrings := xlist.Map(list.Values(), func(v int) string {
    return fmt.Sprintf("Value: %d", v)
})

for s := range asStrings {
    fmt.Println(s)
}
// Output:
// Value: 1
// Value: 2
// Value: 3
AnyMatch
checks if any element in a sequence matches a predicate
AnyMatch[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) bool

A terminal operation that consumes an iterator and returns true if at least one element satisfies the predicate is_ok. The iteration stops as soon as a match is found.

Example:

list := xlist.New[int](1, 3, 4, 5)
hasEvenNumber := xlist.AnyMatch(list.All(), func(_ int, v int) bool {
    return v%2 == 0
})

if hasEvenNumber {
    fmt.Println("The list contains at least one even number.") // This will print
}
AllMatch
checks if all elements in a sequence match a predicate
AllMatch[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) bool

A terminal operation that consumes an iterator and returns true if all elements satisfy the predicate is_ok. The iteration stops as soon as an element fails the predicate.

Example:

list := xlist.New[int](2, 4, 6)
allAreEven := xlist.AllMatch(list.All(), func(_ int, v int) bool {
    return v%2 == 0
})

if allAreEven {
    fmt.Println("All numbers in the list are even.") // This will print
}

Iterator (Sequential traversal of elements)

Iterator()
creates an iterator for sequential traversal
Iterator() *Iterator[T]

Creates an iterator of the list that supports forward and reverse iteration. Sets iterator work range from the beginning to the end.

Example:

list := xlist.New[int](1, 2, 3, 4)

it := list.Iterator()
for it.Next() {
    value, _ := it.Value()
    fmt.Println(value)
}

// Output:
// 1
// 2
// 3
// 4
Iterator( int )
creates an iterator with work interval from the specified index to the last element
Iterator(start int) *Iterator[T]

Creates an iterator for traversal from a specific index to the last element of the work interval.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

it := list.Iterator(2)
for it.Next() {
    value, _ := it.Value()
    fmt.Println(value)
}

// Output:
// 3
// 4
// 5
Iterator( int, int )
creates an iterator for a specific range
Iterator(start int, finish int) *Iterator[T]

Creates an iterator for traversal within a specific range of indices.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

it := list.Iterator(1, 3)
for it.Next() {
    value, _ := it.Value()
    fmt.Println(value)
}

// Output:
// 2
// 3
// 4
Reset( ...int )
resets the iterator with a new range of work
Reset(workRange ...int)

Reset - resets the iterator with a new range of work. Accepts 0, 1, or 2 arguments.

If no arguments are provided, the iterator is reset to traverse from the first to the last element of the container. If 1 argument is provided, it is treated as the start index of the range. If 2 arguments are provided, they define the start and end indexes of the range respectively.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

it := list.Iterator()
for it.Next() {
    value, _ := it.Value()
    fmt.Println(value)
}

fmt.Println("Reset the iterator with new work range:")

it.Reset(1, 3)
for it.Next() {
	value, _ := it.Value()
}

// Output:
// 1
// 2
// 3
// 4
// 5
// Reset the iterator with new work range
// 2
// 3
// 4
SetIndex( int ) (T, bool)
sets the iterator to the specified index
SetIndex(index int) (T, bool)

Set the iterator to the specified index. Returns the element at the new index and a boolean indicating whether the returned value was valid.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()

if value, ok := iter.SetIndex(2); ok {
    fmt.Println(value) // Output: 3	
} else {
	fmt.Println("Invalid value")
}

fmt.Println(iter.Value()) // Output: 3
SetFirst()
sets the iterator to the first element of the container or work range
SetFirst() (T, bool)

Sets the iterator to the first element of the container or work range. Returns the first element and a boolean indicating if the returned value is valid.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()

iter.Next()
fmt.Println(iter.Value()) // Output: 2

iter.SetFirst()
fmt.Println(iter.Value()) // Output: 1

iter = list.Iterator(2)
fmt.Println(iter.Value()) // Output: 3

iter.Next()
fmt.Println(iter.Value()) // Output: 4

iter.SetFirst()
fmt.Println(iter.Value()) // Output: 3
SetLast()
sets the iterator to the last element of the container or work range
SetLast() (T, bool)

Sets the iterator to the last element of the container or work range. Returns the last element and a boolean indicating if the returned value is valid.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()
last, _ := iter.SetLast()
fmt.Println(last) // Output: 5

// Iterator with custom range
iter = list.Iterator(1, 3)
last, _ = iter.SetLast()
fmt.Println(last) // Output: 4
Index()
returns the current index of the iterator
Index() int

Returns the current index of the iterator. If the iterator hasn't been initialized yet, it returns -1.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()
fmt.Println(iter.Index()) // Output: -1 (not initialized yet)

iter.Next()
fmt.Println(iter.Index()) // Output: 0

iter.Next()
fmt.Println(iter.Index()) // Output: 1
Value()
returns the current value of the iterator
Value() (T, bool)

Returns the current value of the iterator and a boolean indicating if the value is valid.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()
value, ok := iter.Value() // ok is false, not initialized yet

iter.Next()
value, ok = iter.Value()
fmt.Println(value, ok) // Output: 1 true
Next()
advances the iterator to the next element
Next() bool

Advances the iterator to the next element. Returns true if successful, false if the end of the range has been reached.

Example:

list := xlist.New[int](1, 2, 3)

iter := list.Iterator()
for iter.Next() {
    value, _ := iter.Value()
    fmt.Println(value)
}

// Output:
// 1
// 2
// 3
Prev()
moves the iterator to the previous element
Prev() bool

Moves the iterator to the previous element. Returns true if successful, false if the beginning of the range has been reached.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()
iter.SetLast() // Start from the end

for iter.Prev() {
    value, _ := iter.Value()
    fmt.Println(value)
}

// Output:
// 4
// 3
// 2
// 1
NextValue()
returns the next value and moves the iterator forward
NextValue() (T, bool)

Returns the next value from the container and moves the iterator forward the iterator. Returns a value and a boolean indicating if the value is valid. Returns false when the end of the range is reached.

Example:

list := xlist.New[int](1, 2, 3)

iter := list.Iterator()
for {
    value, ok := iter.NextValue()
    if !ok {
        break
    }
    fmt.Println(value)
}

// Output:
// 1
// 2
// 3
PrevValue()
returns the previous value and moves the iterator backward
PrevValue() (T, bool)

Returns the previous value from the container and moves the iterator backward. Returns a value and a boolean indicating if the value is valid. Returns false when the beginning of the range is reached.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

iter := list.Iterator()
iter.SetLast() // Start from the end

for {
    value, ok := iter.PrevValue()
    if !ok {
        break
    }
    fmt.Println(value)
}

// Output:
// 4
// 3
// 2
// 1

Bulk processing methods

Find( func(int, T) bool )
finds elements that match specific criteria
Find(is func(index int, object T) bool) *XList[T]

Searches for objects in the list according to criteria defined in the 'is' function and returns a new list with objects that were found.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

// Find all even numbers
evenNumbers := list.Find(func(index int, value int) bool {
    return value%2 == 0
})

fmt.Println(evenNumbers.Size()) // Output: 2
fmt.Println(evenNumbers.AtPtr(0)) // Output: 2
fmt.Println(evenNumbers.AtPtr(1)) // Output: 4
Modify( func(int, T) T )
modifies each element in the collection
Modify(change func(index int, object T) T) *XList[T]

Modifies each element in the collection by applying the provided function. This is useful when the XList is used in a highly concurrent environment, since each 'change' function's logic performs under the list's internal mutex. Returns self for method chaining; return value can be ignored.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

// Multiply each element by 2
list.Modify(func(index int, value int) int {
    return value * 2
})

fmt.Println(list.AtPtr(0)) // Output: 2
fmt.Println(list.AtPtr(1)) // Output: 4
fmt.Println(list.AtPtr(2)) // Output: 6
fmt.Println(list.AtPtr(3)) // Output: 8
fmt.Println(list.AtPtr(4)) // Output: 10
ModifyRev( func(int, T) T )
modifies each element in reverse order
ModifyRev(change func(index int, object T) T) *XList[T]

Modifies each element in the collection by going in reverse order. The function applies the changes starting from the end of the list and moving towards the beginning. Useful when current result depends on previous modified values. Returns self for method chaining; return value can be ignored.

Example:

list := xlist.New[int](1, 2, 3, 4, 5)

// Add index value in reverse (starting from the end)
list.ModifyRev(func(index int, value int) int {
    return value + index
})

fmt.Println(list.AtPtr(0)) // Output: 1 + 4 = 5
fmt.Println(list.AtPtr(1)) // Output: 2 + 3 = 5
fmt.Println(list.AtPtr(2)) // Output: 3 + 2 = 5
fmt.Println(list.AtPtr(3)) // Output: 4 + 1 = 5
fmt.Println(list.AtPtr(4)) // Output: 5 + 0 = 5

Sorting Methods

Sort( func(T, T) bool )
sorts the list using a custom comparator
Sort(compare func(a, b T) bool)

Sorts the list in-place using the provided comparator function. The comparator should return true if the first argument is less than the second.

Example:

list := xlist.New[int](5, 3, 8, 1, 2)

list.Sort(func(a, b int) bool { return a < b })

fmt.Println(list.AtPtr(0)) // Output: 1
fmt.Println(list.AtPtr(1)) // Output: 2
fmt.Println(list.AtPtr(2)) // Output: 3
fmt.Println(list.AtPtr(3)) // Output: 5
fmt.Println(list.AtPtr(4)) // Output: 8

Algorithm: PDQSort (Pattern-Defeating Quicksort)

Sort uses a parallel PDQSort — the same algorithm family used in Go's standard slices package, Rust's standard library, and modern C++ implementations — adapted for a doubly-linked list.

The algorithm combines three strategies:

  • Insertion sort for small segments (≤ 12 elements) — minimal overhead on short runs.
  • Quicksort as the main engine — O(n log n) average with smart pivot selection (median-of-3, Tukey ninther for n ≥ 50). Detects already-sorted and reverse-sorted inputs and handles them in O(n).
  • Heapsort as a fallback — triggered only when too many unbalanced partitions are detected, guaranteeing O(n log n) worst case.

All sorting is done by swapping obj pointers inside existing nodes — no elements are moved or allocated. Recursive sub-problems are dispatched to goroutines (up to GOMAXPROCS-1 parallel workers) when the segment is large enough (≥ 2048 elements).

Benchmark (sort_benchmark_test.go, 100,000 elements, Apple M4 Pro, go test -bench=. -benchmem -benchtime=10s):

The benchmark compares XList.Sort against slices.SortFunc / slices.Sort on identical random data. For XList, data is loaded into the list via Append before each iteration; for slice, data is copied via copy. Only the sort itself is measured (b.StopTimer / b.StartTimer).

Benchmark ns/op B/op allocs/op
XList Sort — struct 2,840,180 1,613 22
Slice Sort — struct 7,235,237 0 0
XList Sort — int 2,451,451 1,946 26
Slice Sort — int 4,610,621 0 0

XList Sort is ~2.5x faster [*] than slices.Sort on this hardware. The small number of allocations (~22–26) comes from goroutine stacks spawned for parallel sub-problems — one allocation per goroutine, unavoidable in Go's concurrency model.

[*]: Although XList uses the same PDQSort algorithm, its single-threaded performance is slightly slower than the native slices.Sort. This is due to the memory layout of a doubly-linked list, which scatters data and is less cache-friendly for the CPU. The overall ~2.5x speedup is achieved by leveraging Go's concurrency to execute the sort in parallel.

Documentation

Index

Constants

This section is empty.

Variables

View Source
var (
	ErrElementNotFound = errors.New("element not found")
	ErrInvalidIndex    = errors.New("invalid index")
	ErrIsNotAPointer   = errors.New("object is not a pointer")
	ErrNoClosure       = errors.New("no function closure")
)

Functions

func AllMatch

func AllMatch[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) bool

AllMatch is a terminal helper that checks whether all elements match the predicate. Example:

list := New[*int]()
list.Append(&val1, &val2, &val3)
allPositive := AllMatch(list.All(), func(_ int, val *int) bool {
	return val != nil && *val > 0
})

if allPositive {
     fmt.Println("All are positive")
}

func AnyMatch

func AnyMatch[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) bool

AnyMatch is a terminal helper that checks whether any element matches the predicate. Example:

list := New[*int]()
list.Append(&val1, &val2, &val3)
hasEven := AnyMatch(list.All(), func(_ int, val *int) bool {
	return val != nil && *val%2 == 0
})

if hasEven {
     fmt.Println("there is even")
}

func Filter

func Filter[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

Filter passes through elements for which the predicate returns true.

Example:

filtered := Filter(list.All(), func(i int, obj *teststruct) bool {
	return obj != nil && i%2 == 0
})

for _, obj := range filtered {
	fmt.Println(obj)
}

func Map

func Map[T, V any](seq iter.Seq[T], transform func(T) V) iter.Seq[V]

Map transforms a sequence of T into a sequence of V. Used to transform data extracted via Values().

Example:

asStrings := Map(list.Values(), func(v int) string {
	return fmt.Sprintf("value=%d", v)
})

for s := range asStrings {
	fmt.Println(s)
}

func SkipWhile

func SkipWhile[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

SkipWhile skips elements while the predicate is true, then yields the rest.

Example:

list := New[*int]()
list.Append(&val1, &val2, &val3)
tail := SkipWhile(list.All(), func(_ int, val *int) bool {
	return val != nil && *val < 10
})

for _, val := range tail {
	if val != nil {
		fmt.Println(*val)
	}
}

func TakeWhile

func TakeWhile[T any](it2 iter.Seq2[int, T], is_ok func(int, T) bool) iter.Seq2[int, T]

TakeWhile yields elements while the predicate remains true. Traversal stops when the first element fails the predicate.

Example:

list := New[*int]()
list.Append(&val1, &val2, &val3)
prefix := TakeWhile(list.All(), func(_ int, val *int) bool {
	return val != nil && *val < 10
})

for _, val := range prefix {
	if val != nil {
		fmt.Println(*val)
	}
}

func ToValues

func ToValues[T any](seq2 iter.Seq2[int, T]) iter.Seq[T]

ToValues transforms a Seq2 iterator (with index and value) to a Seq (values only, without indices).

Example:

for v := range ToValues(list.All()) {
	fmt.Println(v)
}

func WithCount

func WithCount(count int) func(*RangeOptions)

func WithPos

func WithPos(pos int) func(*RangeOptions)

Types

type Compare

type Compare[T any] interface {
	func(a, b T) bool
}

type Iterator

type Iterator[T comparable] struct {
	// contains filtered or unexported fields
}

Iterator : optimal for sequential element passes

func (*Iterator[T]) Index

func (p *Iterator[T]) Index() int

Index : returns current index.

func (*Iterator[T]) Next

func (p *Iterator[T]) Next() bool

func (*Iterator[T]) NextValue

func (p *Iterator[T]) NextValue() (T, bool)

NextValue : returns next value from container and 'true' if value is valid, 'false' in case of the list end value is reached (invalid value).

func (*Iterator[T]) Prev

func (p *Iterator[T]) Prev() bool

func (*Iterator[T]) PrevValue

func (p *Iterator[T]) PrevValue() (T, bool)

PrevValue : returns previous value from container and 'true' if value is valid, 'false' in case of the list begin value is reached (invalid value).

func (*Iterator[T]) Reset

func (p *Iterator[T]) Reset(workRange ...int)

Reset - resets the iterator with a new range of work. If empty, the iterator is reset to pass from the first to the last of the container elements.

func (*Iterator[T]) SetFirst

func (p *Iterator[T]) SetFirst() (T, bool)

SetFirst : returns the first element of the container. If Iterator was initialized with range, then returns the first element of the range.

func (*Iterator[T]) SetIndex

func (p *Iterator[T]) SetIndex(index int) (T, bool)

SetIndex : sets the iterator to the specified index.

func (*Iterator[T]) SetLast

func (p *Iterator[T]) SetLast() (T, bool)

SetLast : returns the last element of the container. If Iterator was initialized with range, then returns the last element of the range.

func (*Iterator[T]) Value

func (p *Iterator[T]) Value() (T, bool)

Value : returns current iterator value.

type RangeOptions

type RangeOptions struct {
	// contains filtered or unexported fields
}

type XList

type XList[T comparable] struct {
	// contains filtered or unexported fields
}

func New

func New[T comparable](objects ...T) *XList[T]

New : create new empty XList container

func (*XList[T]) All

func (p *XList[T]) All(opt ...func(*RangeOptions)) iter.Seq2[int, T]

All returns a forward iterator over the list. Each element is yielded as (index, T). Options: WithPos/WithCount can limit the range.

Example:

for i, obj := range list.All(xlist.WithPos(2), xlist.WithCount(3)) {
	fmt.Println(i, obj)
}

func (*XList[T]) Append

func (p *XList[T]) Append(objects ...T) *XList[T]

Append : appends 'objects' to container. In case of empty objects receiver will be unchanged. Returns self for method chaining; return value can be ignored.

func (*XList[T]) AppendList

func (p *XList[T]) AppendList(dList *XList[T]) *XList[T]

AppendList adds objects to the end of the list (mutating). Returns self for method chaining; return value can be ignored. (-) Add

func (*XList[T]) AppendUnique

func (p *XList[T]) AppendUnique(objects ...T) *XList[T]

AppendUnique : appends element if it doesn't exist in current collection. Returns self for method chaining; return value can be ignored.

func (*XList[T]) At

func (p *XList[T]) At(index int) (T, bool)

At : returns the value at the specified index. Returns the value and a bool flag: true if the value is valid, false if index is out of range. This method is recommended for value types (e.g., XList[int], XList[string]) where you need to distinguish between a valid zero value and a missing element.

func (*XList[T]) AtPtr

func (p *XList[T]) AtPtr(index int) T

AtPtr returns the value at the specified index, or zero value if not found. This method is designed for pointer types (e.g., XList[*User], XList[*MyStruct]) where nil naturally indicates absence - simply check if the returned pointer is nil. For value types, use At() instead to properly distinguish zero values from missing elements.

func (*XList[T]) Backward

func (p *XList[T]) Backward(opt ...func(*RangeOptions)) iter.Seq2[int, T]

Backward returns a reverse iterator over the list (from end to start). Each element is yielded as (index, T). Options: WithPos/WithCount can limit the range.

Example:

for i, obj := range list.Backward(xlist.WithPos(2), xlist.WithCount(2)) {
	fmt.Println(i, obj)
}

func (*XList[T]) Clear

func (p *XList[T]) Clear() *XList[T]

Clear : clear container.

func (*XList[T]) Contains

func (p *XList[T]) Contains(objects ...T) bool

Contains : checks whether the set of objects (the whole set) in the list it returns false if any of them not in the list.

func (*XList[T]) ContainsSome

func (p *XList[T]) ContainsSome(objects ...T) bool

ContainsSome : checks whether any of objects of `objects` is in the list it returns false if no one of them not in the list.

func (*XList[T]) Copy

func (p *XList[T]) Copy() *XList[T]

Copy : returns a copy of the list. It makes shallow copies of objects, so be careful when changing container objects. Consider 'DeepCopy' method to copy the container objects themselves.

func (*XList[T]) CopyRange

func (p *XList[T]) CopyRange(fromPos int, toPos int) (*XList[T], error)

CopyRange : returns a new container with elements of receiver for specified range [fromPos, toPos]. It makes shallow copies of objects, so be careful when changing container objects .

func (*XList[T]) DeepCopy

func (p *XList[T]) DeepCopy(deepCopyFn func(T) T) *XList[T]

DeepCopy : returns a new container with new elements of receiver. It makes deep copies of objects, so you must provide a closure 'deepCopyFn' to make a deep copy of type T.

func (*XList[T]) DeepCopyRange

func (p *XList[T]) DeepCopyRange(fromPos int, toPos int, deepCopyFn func(T) T) (*XList[T], error)

DeepCopyRange : returns a new container with elements from the range [fromPos, toPos]. You must provide a closure 'deepCopyFn' that knows how to make a deep copy of type T.

func (*XList[T]) DeleteAt

func (p *XList[T]) DeleteAt(pos int) (T, error)

DeleteAt : deletes and returns the element at the specified position, or an error if the position is invalid.

func (*XList[T]) DeleteLast

func (p *XList[T]) DeleteLast() (T, error)

func (*XList[T]) Find

func (p *XList[T]) Find(is func(index int, object T) bool) *XList[T]

Find : looking for objects in list according to criteria defined in 'is' function and returns new list with objects that were found.

func (*XList[T]) Insert

func (p *XList[T]) Insert(pos int, objects ...T) error

Insert : inserts object before the 'pos' position if position is out of right range, append element - no error

func (*XList[T]) IsEmpty

func (p *XList[T]) IsEmpty() bool

IsEmpty : returns 'true' if container is empty

func (*XList[T]) IsMarkedAtIndex

func (p *XList[T]) IsMarkedAtIndex(index int) bool

IsMarkedAtIndex : returns 'true' if element at specified index is marked

func (*XList[T]) Iterator

func (p *XList[T]) Iterator(workRange ...int) *Iterator[T]

Iterator : creates an iterator for sequential processing.

'workRange' - the first element of the range is the starting index, the second element is the end index, if only one element is passed, the range of work is from the first element to the last.

func (*XList[T]) LastObject

func (p *XList[T]) LastObject() (T, bool)

LastObject returns the last element in the container. Returns the value and a bool flag: true if the value is valid, false if container is empty. This method is recommended for value types (e.g., XList[int], XList[string]) where you need to distinguish between a valid zero value and an empty container.

func (*XList[T]) LastObjectPtr

func (p *XList[T]) LastObjectPtr() T

LastObjectPtr returns the last element in the container, or zero value if container is empty. This method is designed for pointer types (e.g., XList[*User], XList[*MyStruct]) where nil naturally indicates absence - simply check if the returned pointer is nil. For value types, use LastObject() instead to properly distinguish zero values from empty container.

func (*XList[T]) MarkAll

func (p *XList[T]) MarkAll()

MarkAll : mark all elements

func (*XList[T]) MarkAtIndex

func (p *XList[T]) MarkAtIndex(index int)

MarkAtIndex : mark element at specified index

func (*XList[T]) Modify

func (p *XList[T]) Modify(change func(index int, object T) T) *XList[T]

Modify : modifies each element in collection with function 'change'. Returns self for method chaining; return value can be ignored. Supports concurrency, since each 'change' func logic performs under internal mutex.

func (*XList[T]) ModifyRev

func (p *XList[T]) ModifyRev(change func(index int, object T) T) *XList[T]

ModifyRev : modify each element in collection (go in reverse order) Returns self for method chaining; return value can be ignored.

func (*XList[T]) PDQSort

func (p *XList[T]) PDQSort(compare func(a, b T) bool)

PDQSort sorts the list using a PDQSort algorithm adapted for a doubly-linked list. Swaps only the obj pointers inside existing nodes (no element allocation).

Parameters:

  • compare: A function that compares two elements. Returns true when `a` should be before `b`, otherwise false.

func (*XList[T]) Replace

func (p *XList[T]) Replace(pos int, obj T) error

Replace : replaces element at position 'pos' to 'obj'. Returns 'true' if replaced, 'false' if not

func (*XList[T]) ReplaceLast

func (p *XList[T]) ReplaceLast(obj T) error

ReplaceLast : replaces last element, returns 'true' if replaced, 'false' if not.

func (*XList[T]) Set

func (p *XList[T]) Set(objects ...T) *XList[T]

Set : set 'objects' to container. In case of empty objects receiver will be unchanged. Returns self for method chaining; return value can be ignored.

func (*XList[T]) Size

func (p *XList[T]) Size() int

Size : returns size of container.

func (*XList[T]) Slice

func (p *XList[T]) Slice() []T

Slice : get all collection objects as a slice

func (*XList[T]) Sort

func (p *XList[T]) Sort(compare func(a, b T) bool)

Sort sorts the list according to the provided comparison function.

Parameters:

  • compare: A function that compares two elements. Returns true when `a` have to be before `b`, otherwise false.

func (*XList[T]) Splice

func (p *XList[T]) Splice(dList *XList[T]) *XList[T]

Splice : move content from 'dList' to receiver at its tail (appends container - mutating). (!) 'dList' is destroyed, it becomes empty. (-) Move

func (*XList[T]) SpliceAtPos

func (p *XList[T]) SpliceAtPos(pos int, dList *XList[T]) error

SpliceAtPos : inserts (moves) content from 'dList' to receiver at position 'pos'. (!) 'dList' is destroyed, it becomes empty. (-) MoveAtPos

func (*XList[T]) Swap

func (p *XList[T]) Swap(i, j int) error

Swap : swapping 2 elements in the list.

func (*XList[T]) UnmarkAll

func (p *XList[T]) UnmarkAll()

UnmarkAll : clear mark of all elements

func (*XList[T]) UnmarkAtIndex

func (p *XList[T]) UnmarkAtIndex(index int)

UnmarkAtIndex : clear mark of element at specified index

func (*XList[T]) Values

func (p *XList[T]) Values(opt ...func(*RangeOptions)) iter.Seq[T]

Values returns a forward iterator of values only (without indices). Equivalent to ToValues(list.All(...)).

Example:

for v := range list.Values() {
	fmt.Println(v)
}

func (*XList[T]) ValuesBackward

func (p *XList[T]) ValuesBackward(opt ...func(*RangeOptions)) iter.Seq[T]

ValuesBackward returns a reverse iterator of values only (without indices). Equivalent to ToValues(list.Backward(...)).

Example:

for v := range list.ValuesBackward() {
	fmt.Println(v)
}

Jump to

Keyboard shortcuts

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