gopowerseq

command module
v0.0.4 Latest Latest
Warning

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

Go to latest
Published: May 28, 2025 License: MIT Imports: 1 Imported by: 0

README

Documentation

gopowerseq library provides a set of standard operators working with sequences in Go. go1.23 (2024-08-13) introduced iterators (iter.Seq[T] interface) that can be treated as a lazy sequences known from other programming languages like C#, JS, F#, Clojure, Python, ... . Read Sequences in Go series to better understand iterators in Go, it also presents how to implement gopowerseq operators from scratch. This library is a port of the JS counterpart powerseq

isEven := func(x int) bool { return x%2 == 0 }

var numbersSlice []int = []int{1, 2, 3, 4, 5}
var numbersIter iter.Seq[int] = seq.Of(1, 2, 3, 4, 5) // slices.Values(numbersSlice)

// 'seq' package - calling single operator taking input of type 'iter.Seq[T]'
var evenNumbers iter.Seq[int] = seq.Filter(isEven)(numbersIter)
for n := range evenNumbers {
	fmt.Println(n) // 2, 4
}

// 'seq' package - chaining many operators
var items []int = seq.Pipe3(
	seq.Range(0, math.MaxInt64),
	seq.Filter(func(x int) bool { return x%2 == 0 }),
	seq.Take[int](5),
	seq.ToSlice[int]())
fmt.Println(items) // [0 2 4 6 8]

// 'seqs' package - calling single operator taking input of type 'slice'
var chars = []string{"a", "b", "c"}
for n, c := range seqs.Zip(numbersSlice, chars) {
	fmt.Println(n, "-", c) // "1 - a", "2 - b", "3 - c"
}
  • operators from seq package take iter.Seq[] and return functions func (iter.Seq[]) iter.Seq[], there are "curried" so we can Pipe many operators easily
  • operators from seqs package take slices []T and return sequences iter.Seq[]
  • for some operators a special counterparts ending with P are provided (ConcatP,ExceptP,InterleaveP,IntersectP,JoinP,SequenceEqualP, UnionP, ZipP), those functions must be used inside Pipe(..., opp()), so we call Concat([1,2,3], [4,5,6]) or Pipe([1,2,3], ConcatP([4,5,6]) )

operators

  • creation - Of, Empty, Entries, Range, Repeat, RepeatValue
  • filtering - Filter, Skip, SkipWhile, Take, TakeWhile
  • mapping - Map, FlatMap, FlatMapR
  • partitioning - Pairwise, Windowed, PartitionBy, Chunk, Combinations
  • merging - Join, Zip, Interleave, Interpose
  • grouping - GroupBy, GroupByV, CountBy
  • set - Except, Intersect, Union, Distinct, DistinctBy, DistinctUntilChanged
  • conversion - ToSlice, ToMap, ToMapV, ToTuples
  • aggregation - Reduce, ReduceA, Average, Count, Sum
  • quantifiers - All, Any
  • concatenation - Concat
  • equality - SequenceEqual
  • element - First
  • misc - Memoize, Share, Expand, Scan
// helpers
func IsEven(n int) bool       { return n%2 == 0 }
func Plus(a, b int) int       { return a + b }
func GetLen(next string) int  { return len(next) }
func Identity[T any](val T) T { return val }

// operators
seq.All(IsEven)(seq.Of(2, 4, 6))  // true
seq.All(IsEven)(seq.Of(2, 4, 5, 6)) // false

seq.Any(IsEven)(seq.Of(1, 3, 5))  // false
seq.Any(IsEven)(seq.Of(1, 3, 4, 5)) // true

seq.Average[int]()(seq.Of(5, 10, 15)) // 10
seq.AverageFunc(GetLen)(seq.Of("a", "bb", "ccc")) // 2

seq.Chunk[int](2)(seq.Of(5, 10, 15, 50, 100)) // [5 10], [15 50], [100]

seq.Combinations[int](2)(seq.Of(5, 10, 15)) // [5 10], [5 15], [10 15]

seq.Concat(seq.Of(1, 2), seq.Of[int](), seq.Of(3)) // 1, 2, 3

seq.Count[int]()(seq.Of(1, 2, 3, 4)) // 4
seq.CountFunc(IsEven)(seq.Of(1, 2, 3, 4)) // 2

seq.CountBy(GetLen)(seq.Of("a", "bb", "c", "dddd")) // map[1:2 2:1 4:1]

seq.Distinct[int]()(seq.Of(1, 2, 1, 3, 4, 2)) // 1, 2, 3, 4
seq.DistinctFunc(GetLen)(seq.Of("a", "bb", "c", "dddd")) // 1, 2, 4
seq.DistinctBy(GetLen)(seq.Of("a", "bb", "c", "dddd")) // a, bb, dddd
seq.DistinctUntilChanged[int]()(seq.Of(1, 2, 2, 3, 3, 1, 4)) // 1, 2, 3, 1, 4
seq.DistinctUntilChangedFunc(GetLen)(seq.Of("a", "b", "cc", "d", "e")) // a, cc, d

seq.Empty[int]()

seq.Entries(map[int]string{1: "one", 2: "two"}) // {2 two}, {1 one}

seq.Except(seq.Of(1, 2, 2, 3, 3), seq.Of(3, 3, 4, 4)) // 1, 2

expanded := seq.Expand(func(str string) iter.Seq[string] {
	if len(str) > 1 {
		return slices.Values(strings.Split(str, ""))
	} else {
		return seq.Empty[string]()
	}
})(seq.Of("a", "xy", "b")) // "a", "xy", "b", "x", "y"

seq.Filter(IsEven)(seq.Of(1, 2, 2, 4, 5, 7, 8, 10)) // 2, 2, 4, 8, 10

seq.Find(IsEven)(seq.Of(1, 3, 5, 6, 5, 4)) // val: 6, index: 3
seq.Find(IsEven)(seq.Of(1, 3, 5, 5)) // val: 0, index: -1

flatten := seq.FlatMap(func(n int) iter.Seq[string] {
	return slices.Values(slices.Repeat([]string{strconv.Itoa(n)}, n))
})(seq.Of(1, 2, 3)) // "1", "2", "2", "3", "3", "3"

seq.GroupBy(GetLen)(seq.Of("a", "bb", "c")) // map[1:[a c] 2:[bb]]
seq.GroupByV(GetLen, strings.ToUpper)(seq.Of("a", "bb", "c")) // map[1:[A C] 2:[BB]]

seq.Interleave(seq.Of(1, 2, 3), seq.Of(5, 10), seq.Of(-1, -2)) // 1, 5, -1, 2, 10, -2

seq.Interpose(0)(seq.Of(1, 2, 3)) // 1, 0, 2, 0, 3

seq.Intersect(seq.Of(1, 2, 3), seq.Of(2, 3, 4))  //  2, 3
seq.IntersectFunc(seq.Of("a", "bb"), seq.Of("c", "ddd", "ee"), GetLen) // "c", "ee"

seq.Join(seq.Of(1, 2, 3), seq.Of("a", "bbb", "ccc"), Identity, GetLen) // {1 a}, {3 bbb}, {3 ccc}

seq.JoinFunc(seq.Of(1, 2, 3), seq.Of("a", "bbb", "ccc"), Identity, GetLen,
	func(n int, s string) string {
		return fmt.Sprint(n, "-", s)
	}) // 1-a, 3-bbb, 3-ccc

seq.Map(IsEven)(seq.Of(1, 2, 3)) // false, true, false

myIterState := 0
myIter := func(yield func(int) bool) {
	for {
		if !yield(myIterState) {
			return
		}
		myIterState++
	}
}
memoized := seq.Take[int](3)(seq.Memoize[int]()(myIter))
memoized // 0, 1, 2
memoized // 0, 1, 2 (without calling Memoize: 2, 3, 4)

seq.Of(1, 2, 3) // 1, 2, 3

seq.Pairwise[int]()(seq.Of(1, 2, 3, 4))  // {1 2}, {2 3}, {3 4}
seq.PairwiseFunc(func(a, b int) []int { return []int{a, b} })(seq.Of(1, 2, 3, 4)) // [1 2], [2 3], [3 4]

seq.PartitionBy(IsEven)(seq.Of(1, 3, 4, 6, 7, 8)) // [1 3], [4 6], [7], [8]

seq.Range(8, 4) // 8, 9, 10, 11

seq.Reduce(Plus)(seq.Of(1, 2, 3)) // 6
seq.ReduceA(func(s string, b int) string { return fmt.Sprint(s, "-", b) }, "")(seq.Of(1, 2, 3)) // "-1-2-3"

seq.Repeat[int](3)(seq.Of(1, 2))  // 1, 2, 1, 2, 1, 2
seq.Take[int](5)(seq.Repeat[int](-1)(seq.Of(1, 2)))  // 1, 2, 1, 2, 1

seq.RepeatValue(12, 3)  // 12, 12, 12
seq.Take[int](4)(seq.RepeatValue(12, -1)))  // 12, 12, 12, 12

seq.Scan(func(s string, b int) string { return fmt.Sprint(s, "-", b) }, "")(seq.Of(1, 2, 3))
// "", "-1", "-1-2", "-1-2-3"

seq.SequenceEqual(seq.Of(1, 2, 3), seq.Of(1, 2, 3))  // true
seq.SequenceEqual(seq.Of(1, 2, 3), seq.Of(1, 2))  // false

shared := seq.Share[int]()(seq.Of(1, 2, 3))

seq.Take[int](2)(shared) // 1, 2
seq.Take[int](2)(shared) // 3 (without calling Share: 1, 2)

seq.Skip[int](2)(seq.Of(1, 2, 3, 4)) // 3, 4

seq.SkipWhile(IsEven)(seq.Of(2, 4, 3, 4, 7, 8)) // 3, 4, 7, 8

seq.Sum[int]()(seq.Of(1, 2, 3))  // 6
seq.SumFunc(GetLen)(seq.Of("a", "bb", "c"))     // 4

seq.Take[int](2)(seq.Of(1, 2, 3, 4)) // 1, 2

seq.TakeWhile(IsEven)(seq.Of(2, 4, 3, 4, 7, 8)) // 2, 4

seq.ToMap(GetLen)(seq.Of("a", "bb", "c", "dddd"))  // map[1:c 2:bb 4:dddd]
seq.ToMapV(GetLen, strings.ToUpper)(seq.Of("a", "bb", "c", "dddd")) // map[1:C 2:BB 4:DDDD]

seq.ToSlice[int]()(seq.Of(1, 2, 3))  // [1 2 3]

seq.ToTuples[int, string]()(maps.All(map[int]string{1: "one", 2: "two"}))  // {1 one}, {2 two}

seq.Union(seq.Of(1, 2, 3), seq.Of(2, 3, 4, 4))  //  1, 2, 3, 4
seq.UnionFunc(seq.Of("a", "bb"), seq.Of("c", "ddd", "ee"), GetLen)  // "a", "bb", "ddd"

seq.Windowed[int](3)(seq.Of(1, 222, 3, 44, 5)) // [1 222 3], [222 3 44], [3 44 5]

seq.Zip(seq.Of(1, 2, 3), seq.Of("a", "b"))  // {1 a}, {2 b}
seq.ZipFunc(seq.Of(1, 2, 3), seq.Of(10, 100), Plus) // 11, 102

Documentation

The Go Gopher

There is no documentation for this package.

Directories

Path Synopsis
internal

Jump to

Keyboard shortcuts

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