containeriter

package
v0.0.18 Latest Latest
Warning

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

Go to latest
Published: Dec 19, 2024 License: MIT Imports: 4 Imported by: 0

Documentation

Overview

containeriter defines iterator source/collector that corresponds to std library `container/*`.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func CollectList

func CollectList[V any](seq iter.Seq[V]) *list.List

Collect collects values from seq into a new list and returns it.

func CollectRing

func CollectRing[V any](seq iter.Seq[V]) *ring.Ring

Collect collects values from seq into a new ring and returns it.

func Heap

func Heap[V any](h heap.Interface) iter.Seq[V]

Heap returns an iterator over heap.Interface. Consuming iter.Seq[V] also consumes h. To avoid this, callers must clone input h before passing to Heap.

Example
package main

import (
	"cmp"
	"container/heap"
	"fmt"

	"github.com/ngicks/go-iterator-helper/hiter/containeriter"
	"github.com/ngicks/go-iterator-helper/x/exp/xiter"
)

var _ heap.Interface = (*sliceHeap)(nil)

type sliceHeap []int

func (s *sliceHeap) Len() int           { return len(*s) }
func (s *sliceHeap) Less(i, j int) bool { return cmp.Less((*s)[i], (*s)[j]) }
func (s *sliceHeap) Swap(i, j int)      { (*s)[i], (*s)[j] = (*s)[j], (*s)[i] }
func (s *sliceHeap) Push(x any)         { (*s) = append((*s), x.(int)) }
func (s *sliceHeap) Pop() any {
	p := (*s)[len(*s)-1]
	// Zeroing out the removed part of slice.
	// This does nothing for types like int.
	// If the type is pointer or struct that contains pointer,
	// zeroing out lets GC clean up now-unused elements.
	(*s)[len(*s)-1] = 0
	*s = (*s)[:len(*s)-1]
	return p
}

func main() {
	h := &sliceHeap{0, 6, 1, 3, 2, 8, 210, 3, 7, 9, 2, 1, 54, 7}
	heap.Init(h)

	for num := range xiter.Limit(containeriter.Heap[int](h), 5) {
		fmt.Printf("%d, ", num)
	}

	fmt.Println("...stopped here. and...")

	for num := range containeriter.Heap[int](h) {
		fmt.Printf("%d, ", num)
		if h.Len() == 1 {
			break
		}
	}

	for num := range containeriter.Heap[int](h) {
		fmt.Printf("%d\n", num)
	}

}
Output:

0, 1, 1, 2, 2, ...stopped here. and...
3, 3, 6, 7, 7, 8, 9, 54, 210

func LinkRingSeq

func LinkRingSeq[V any](r *ring.Ring, seq iter.Seq[V]) *ring.Ring

LinkRingSeq links all values from seq to r and returns r.

func ListAll

func ListAll[V any](l *list.List) iter.Seq[V]

ListAll returns an iterator over all element of l starting from l.Front(). ListAll assumes Values of all element are type V. If other than that or nil, the returned iterator may panic on invocation.

Example
package main

import (
	"container/list"
	"fmt"
	"slices"

	"github.com/ngicks/go-iterator-helper/hiter/containeriter"
)

func main() {
	l := list.New()

	for _, s := range []string{"foo", "bar", "baz"} {
		l.PushBack(s)
	}

	fmt.Printf("all:              %#v\n", slices.Collect(containeriter.ListAll[string](l)))
	fmt.Printf("backward:         %#v\n", slices.Collect(containeriter.ListBackward[string](l)))
	fmt.Printf("element all:      %#v\n", slices.Collect(containeriter.ListElementAll[string](l.Front().Next())))
	fmt.Printf("element backward: %#v\n", slices.Collect(containeriter.ListElementBackward[string](l.Front().Next())))
}
Output:

all:              []string{"foo", "bar", "baz"}
backward:         []string{"baz", "bar", "foo"}
element all:      []string{"bar", "baz"}
element backward: []string{"bar", "foo"}

func ListBackward

func ListBackward[V any](l *list.List) iter.Seq[V]

ListBackward returns an iterator over all element of l starting from l.Back(). ListBackward assumes Values of all element are type V. If other than that or nil, the returned iterator may panic on invocation.

func ListElementAll

func ListElementAll[V any](ele *list.Element) iter.Seq[V]

ListElementAll returns an iterator over from ele to end of the list. ListElementAll assumes Values of all element are type V. If other than that or nil, the returned iterator may panic on invocation.

func ListElementBackward

func ListElementBackward[V any](ele *list.Element) iter.Seq[V]

ListElementBackward returns an iterator over from ele to start of the list. ListElementBackward assumes Values of all element are type V. If other than that or nil, the returned iterator may panic on invocation.

func PushBackListSeq

func PushBackListSeq[V any](l *list.List, seq iter.Seq[V]) *list.List

PushBackListSeq pushes-back the values from seq to l and returns the extended list.

func PushFrontListSeq

func PushFrontListSeq[V any](l *list.List, seq iter.Seq[V]) *list.List

PushFrontListSeq pushes-front the values from seq to l and returns the extended list.

func PushHeapSeq

func PushHeapSeq[H heap.Interface, V any](h H, seq iter.Seq[V]) H

PushHeapSeq pushes the values from seq to h and returns the extended heap. The complexity is O(n) where n = length of total heap content after all element from seq is appended.

func RingAll

func RingAll[V any](r *ring.Ring) iter.Seq[V]

Ring returns an iterator over r. The returned iterator generates data assuming Values of all ring elements are type V. It yields r.Value traversing by consecutively calling Next, and stops when it finds r again. Removing r from the ring after it started iteration may make it iterate forever.

Example
package main

import (
	"container/ring"
	"fmt"
	"slices"

	"github.com/ngicks/go-iterator-helper/hiter/containeriter"
)

func main() {
	ringBufSize := 5
	r := ring.New(ringBufSize)

	for i := range ringBufSize {
		r.Value = i
		r = r.Next()
	}

	fmt.Printf("all:      %#v\n", slices.Collect(containeriter.RingAll[int](r)))
	fmt.Printf("backward: %#v\n", slices.Collect(containeriter.RingBackward[int](r.Prev())))

	// Now, we'll demonstrate buffer like usage of ring.

	pushBack := func(v int) {
		r.Value = v
		r = r.Next()
	}

	pushBack(12)
	pushBack(5)
	fmt.Printf("1:        %#v\n", slices.Collect(containeriter.RingAll[int](r)))

	pushBack(8)
	fmt.Printf("2:        %#v\n", slices.Collect(containeriter.RingAll[int](r)))

	pushBack(36)
	fmt.Printf("3:        %#v\n", slices.Collect(containeriter.RingAll[int](r)))

}
Output:

all:      []int{0, 1, 2, 3, 4}
backward: []int{4, 3, 2, 1, 0}
1:        []int{2, 3, 4, 12, 5}
2:        []int{3, 4, 12, 5, 8}
3:        []int{4, 12, 5, 8, 36}
Example (Moving_average)

ExampleRingAll_moving_average demonstrates buffer-like usage of RingAll.

package main

import (
	"container/ring"
	"fmt"
	"iter"
	"slices"

	"github.com/ngicks/go-iterator-helper/hiter"
	"github.com/ngicks/go-iterator-helper/hiter/containeriter"
	"github.com/ngicks/go-iterator-helper/x/exp/xiter"
)

func dynamicWindow[V any](size int, seq iter.Seq[V]) iter.Seq[iter.Seq[V]] {
	return func(yield func(iter.Seq[V]) bool) {
		var (
			full     = false
			bufStart = ring.New(size)
		)
		buf := bufStart
		for v := range seq {
			if !full {
				buf.Value = v
				buf = buf.Next()
				if buf == bufStart {
					full = true
					if !yield(containeriter.RingAll[V](buf)) {
						return
					}
				}
				continue
			}
			buf.Value = v
			buf = buf.Next()
			if !yield(containeriter.RingAll[V](buf)) {
				return
			}
		}
	}
}

func main() {
	windowSize := 5
	src := slices.Values([]int{1, 0, 1, 0, 1, 0, 5, 3, 2, 3, 4, 6, 5, 3, 6, 7, 7, 8, 9, 5, 7, 7, 8})

	first := true
	for avg := range xiter.Map(
		func(s iter.Seq[int]) float64 {
			return float64(hiter.Sum(s)) / float64(windowSize)
		},
		dynamicWindow(windowSize, src),
	) {
		if !first {
			fmt.Print(", ")
		}
		fmt.Printf("%02.1f", avg)
		first = false
	}
	fmt.Println()
}
Output:

0.6, 0.4, 1.4, 1.8, 2.2, 2.6, 3.4, 3.6, 4.0, 4.2, 4.8, 5.4, 5.6, 6.2, 7.4, 7.2, 7.2, 7.2, 7.2

func RingBackward

func RingBackward[V any](r *ring.Ring) iter.Seq[V]

RingBackward returns an iterator over r. The returned iterator generates data assuming Values of all ring elements are type V. It yields r.Value traversing by consecutively calling Prev, and stops when it finds r again. Removing r from the ring after it started iteration may make it iterate forever.

Types

This section is empty.

Jump to

Keyboard shortcuts

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