Documentation
¶
Overview ¶
Package collection seeks to provide an expressive and readable way of working with basic data structures in Go.
As a former .NET developer, I deeply missed writing programs in the style of Linq. Doing so enables concurrent/ parallel reactive programs to be written in a snap. Go's functional nature enables us to have a very similar, if more verbose, experience.
Take for example the scenario of printing the number of Go source files in a directory. Using this package, this takes only a few lines:
myDir := collection.Directory{
Location: "./",
}
results := myDir.Enumerate(context.Background()).Where(func(x interface{}) bool {
return strings.HasSuffix(x.(string), ".go")
})
fmt.Println(results.CountAll())
A directory is a collection of filesystem entries, so we're able to iterate through them using the "Enumerate" function. From there, we filter on only file names that end with ".go". Finally, we print the number of entries that were encountered.
This is a trivial example, but imagine building more elaborate pipelines. Maybe take advantage of the `SelectParallel` function which allows multiple goroutines to process a single transform at once, with their results being funnelled into the next phase of the pipeline. Suddenly, injecting new steps can be transparent.
Index ¶
- Constants
- Variables
- func All[T any](subject Enumerable[T], p Predicate[T]) bool
- func Any[T any](iterator Enumerable[T]) bool
- func Anyp[T any](iterator Enumerable[T], p Predicate[T]) bool
- func Count[T any](iter Enumerable[T], p Predicate[T]) int
- func CountAll[T any](iter Enumerable[T]) int
- func ElementAt[T any](iter Enumerable[T], n uint) T
- func First[T any](subject Enumerable[T]) (retval T, err error)
- func IsErrorMultipleElements(err error) bool
- func IsErrorNoElements(err error) bool
- func Last[T any](iter Enumerable[T]) T
- func Single[T any](iter Enumerable[T]) (retval T, err error)
- func Singlep[T any](iter Enumerable[T], pred Predicate[T]) (retval T, err error)
- func ToSlice[T any](iter Enumerable[T]) []T
- func UCount[T any](iter Enumerable[T], p Predicate[T]) uint
- func UCountAll[T any](iter Enumerable[T]) uint
- type Comparator
- type Dictionary
- func (dict *Dictionary) Add(word string) (wasAdded bool)
- func (dict *Dictionary) Clear()
- func (dict Dictionary) Contains(word string) bool
- func (dict Dictionary) Enumerate(ctx context.Context) Enumerator[string]
- func (dict *Dictionary) Remove(word string) (wasRemoved bool)
- func (dict Dictionary) Size() int64
- type Directory
- type DirectoryOptions
- type Enumerable
- func AsEnumerable[T any](entries ...T) Enumerable[T]
- func Empty[T any]() Enumerable[T]
- func Merge[T any](channels ...Enumerable[T]) Enumerable[T]
- func ParallelSelect[T any, E any](original Enumerable[T], operation Transform[T, E]) Enumerable[E]
- func Reverse[T any](original Enumerable[T]) Enumerable[T]
- func Select[T any, E any](subject Enumerable[T], transform Transform[T, E]) Enumerable[E]
- func SelectMany[T any, E any](subject Enumerable[T], toMany Unfolder[T, E]) Enumerable[E]
- func Skip[T any](subject Enumerable[T], n uint) Enumerable[T]
- func Take[T any](subject Enumerable[T], n uint) Enumerable[T]
- func TakeWhile[T any](subject Enumerable[T], criteria func(T, uint) bool) Enumerable[T]
- func Where[T any](original Enumerable[T], p Predicate[T]) Enumerable[T]
- type EnumerableSlice
- type Enumerator
- func (iter Enumerator[T]) All(p Predicate[T]) bool
- func (iter Enumerator[T]) AsEnumerable() Enumerable[T]
- func (iter Enumerator[T]) Count(p Predicate[T]) int
- func (iter Enumerator[T]) CountAll() int
- func (iter Enumerator[T]) Discard()
- func (iter Enumerator[T]) ElementAt(n uint) T
- func (iter Enumerator[T]) Last() (retval T)
- func (iter Enumerator[T]) Merge(others ...Enumerator[T]) Enumerator[T]
- func (iter Enumerator[T]) Reverse() Enumerator[T]
- func (iter Enumerator[T]) Skip(n uint) Enumerator[T]
- func (iter Enumerator[T]) Take(n uint) Enumerator[T]
- func (iter Enumerator[T]) TakeWhile(criteria func(T, uint) bool) Enumerator[T]
- func (iter Enumerator[T]) Tee() (Enumerator[T], Enumerator[T])
- func (iter Enumerator[T]) ToSlice() []T
- func (iter Enumerator[T]) UCount(p Predicate[T]) uint
- func (iter Enumerator[T]) UCountAll() uint
- func (iter Enumerator[T]) Where(predicate Predicate[T]) Enumerator[T]
- type LRUCache
- type LinkedList
- func (list *LinkedList[T]) AddBack(entry T)
- func (list *LinkedList[T]) AddFront(entry T)
- func (list *LinkedList[T]) Enumerate(ctx context.Context) Enumerator[T]
- func (list *LinkedList[T]) Get(pos uint) (T, bool)
- func (list *LinkedList[T]) IsEmpty() bool
- func (list *LinkedList[T]) Length() uint
- func (list *LinkedList[T]) PeekBack() (T, bool)
- func (list *LinkedList[T]) PeekFront() (T, bool)
- func (list *LinkedList[T]) RemoveBack() (T, bool)
- func (list *LinkedList[T]) RemoveFront() (T, bool)
- func (list *LinkedList[T]) Sort(comparator Comparator[T]) error
- func (list *LinkedList[T]) String() string
- func (list *LinkedList[T]) Swap(x, y uint) error
- func (list *LinkedList[T]) ToSlice() []T
- type List
- func (l *List[T]) Add(entries ...T)
- func (l *List[T]) AddAt(pos uint, entries ...T)
- func (l *List[T]) Enumerate(ctx context.Context) Enumerator[T]
- func (l *List[T]) Get(pos uint) (T, bool)
- func (l *List[T]) IsEmpty() bool
- func (l *List[T]) Length() uint
- func (l *List[T]) Remove(pos uint) (T, bool)
- func (l *List[T]) Set(pos uint, val T) bool
- func (l *List[T]) String() string
- func (l *List[T]) Swap(x, y uint) bool
- type Predicate
- type Queue
- type Stack
- type Transform
- type Unfolder
Examples ¶
- Dictionary.Add
- Dictionary.Clear
- Dictionary.Enumerate
- Dictionary.Remove
- Directory.Enumerate
- EnumerableSlice.Enumerate
- Enumerator.Count
- Enumerator.CountAll
- Enumerator.ElementAt
- Enumerator.Last
- Enumerator.Reverse
- Enumerator.Skip
- Enumerator.Take
- Enumerator.TakeWhile
- Enumerator.Tee
- Enumerator.UCount
- Enumerator.UCountAll
- Enumerator.Where
- First
- LRUCache
- LRUCache.Enumerate
- LRUCache.EnumerateKeys
- Last
- LinkedList.AddBack
- LinkedList.AddFront
- LinkedList.Enumerate
- LinkedList.Get
- LinkedList.Sort
- LinkedList.String
- LinkedList.Swap
- List.AddAt
- Merge
- NewLinkedList
- NewQueue
- NewStack
- Queue.Add
- Queue.IsEmpty
- Queue.Next
- Select
- SelectMany
- Skip
- Take
- TakeWhile
- UCount
- UCountAll
- Where
Constants ¶
const ( DirectoryOptionsExcludeFiles = 1 << iota DirectoryOptionsExcludeDirectories DirectoryOptionsRecursive )
These constants define all of the supported options for configuring a `Directory`
Variables ¶
var (
ErrUnexpectedType = errors.New("value was of an unexpected type")
)
A collection of errors that may be thrown by functions in this file.
Functions ¶
func All ¶
func All[T any](subject Enumerable[T], p Predicate[T]) bool
All tests whether or not all items present in an Enumerable meet a criteria.
func Any ¶
func Any[T any](iterator Enumerable[T]) bool
Any tests an Enumerable to see if there are any elements present.
func Anyp ¶
func Anyp[T any](iterator Enumerable[T], p Predicate[T]) bool
Anyp tests an Enumerable to see if there are any elements present that meet a criteria.
func Count ¶
func Count[T any](iter Enumerable[T], p Predicate[T]) int
Count iterates over a list and keeps a running tally of the number of elements which satisfy a predicate.
func CountAll ¶
func CountAll[T any](iter Enumerable[T]) int
CountAll iterates over a list and keeps a running tally of how many it's seen.
func ElementAt ¶
func ElementAt[T any](iter Enumerable[T], n uint) T
ElementAt retreives an item at a particular position in an Enumerator.
func First ¶
func First[T any](subject Enumerable[T]) (retval T, err error)
First retrieves just the first item in the list, or returns an error if there are no elements in the array.
Example ¶
empty := collection.NewQueue[int]() notEmpty := collection.NewQueue(1, 2, 3, 4) fmt.Println(collection.First[int](empty)) fmt.Println(collection.First[int](notEmpty))
Output: 0 enumerator encountered no elements 1 <nil>
func IsErrorMultipleElements ¶
IsErrorMultipleElements determines whether or not the given error is the result of multiple values being returned when one or zero were expected.
func IsErrorNoElements ¶
IsErrorNoElements determines whethr or not the given error is the result of no values being returned when one or more were expected.
func Last ¶
func Last[T any](iter Enumerable[T]) T
Last retreives the item logically behind all other elements in the list.
Example ¶
subject := collection.NewList(1, 2, 3, 4) fmt.Println(collection.Last[int](subject))
Output: 4
func Single ¶
func Single[T any](iter Enumerable[T]) (retval T, err error)
Single retreives the only element from a list, or returns nil and an error.
func Singlep ¶
func Singlep[T any](iter Enumerable[T], pred Predicate[T]) (retval T, err error)
Singlep retrieces the only element from a list that matches a criteria. If no match is found, or two or more are found, `Singlep` returns nil and an error.
func ToSlice ¶
func ToSlice[T any](iter Enumerable[T]) []T
ToSlice places all iterated over values in a Slice for easy consumption.
func UCount ¶
func UCount[T any](iter Enumerable[T], p Predicate[T]) uint
UCount iterates over a list and keeps a running tally of the number of elements satisfy a predicate.
Example ¶
subject := collection.NewStack[any](9, 'a', "str1")
result := collection.UCount[interface{}](subject, func(a interface{}) bool {
_, ok := a.(string)
return ok
})
fmt.Println(result)
Output: 1
Types ¶
type Comparator ¶
Comparator is a function which evaluates two values to determine their relation to one another. - Zero is returned when `a` and `b` are equal. - Positive numbers are returned when `a` is greater than `b`. - Negative numbers are returned when `a` is less than `b`.
type Dictionary ¶
type Dictionary struct {
// contains filtered or unexported fields
}
Dictionary is a list of words. It is implemented as a Trie for memory efficiency.
func (*Dictionary) Add ¶
func (dict *Dictionary) Add(word string) (wasAdded bool)
Add inserts a word into the dictionary, and returns whether or not that word was a new word.
Time complexity: O(m) where 'm' is the length of word.
Example ¶
subject := &collection.Dictionary{}
const example = "hello"
fmt.Println(subject.Contains(example))
fmt.Println(subject.Size())
subject.Add(example)
fmt.Println(subject.Contains(example))
fmt.Println(subject.Size())
Output: false 0 true 1
func (*Dictionary) Clear ¶
func (dict *Dictionary) Clear()
Clear removes all items from the dictionary.
Example ¶
subject := &collection.Dictionary{}
subject.Add("hello")
subject.Add("world")
fmt.Println(subject.Size())
fmt.Println(collection.CountAll[string](subject))
subject.Clear()
fmt.Println(subject.Size())
fmt.Println(collection.Any[string](subject))
Output: 2 2 0 false
func (Dictionary) Contains ¶
func (dict Dictionary) Contains(word string) bool
Contains searches the Dictionary to see if the specified word is present.
Time complexity: O(m) where 'm' is the length of word.
func (Dictionary) Enumerate ¶
func (dict Dictionary) Enumerate(ctx context.Context) Enumerator[string]
Enumerate lists each word in the Dictionary alphabetically.
Example ¶
subject := &collection.Dictionary{}
subject.Add("world")
subject.Add("hello")
upperCase := collection.Select[string](subject, strings.ToUpper)
for word := range subject.Enumerate(context.Background()) {
fmt.Println(word)
}
for word := range upperCase.Enumerate(context.Background()) {
fmt.Println(word)
}
Output: hello world HELLO WORLD
func (*Dictionary) Remove ¶
func (dict *Dictionary) Remove(word string) (wasRemoved bool)
Remove ensures that `word` is not in the Dictionary. Returns whether or not an item was removed.
Time complexity: O(m) where 'm' is the length of word.
Example ¶
const world = "world"
subject := &collection.Dictionary{}
subject.Add("hello")
subject.Add(world)
fmt.Println(subject.Size())
fmt.Println(collection.CountAll[string](subject))
subject.Remove(world)
fmt.Println(subject.Size())
fmt.Println(collection.CountAll[string](subject))
fmt.Println(collection.Any[string](subject))
Output: 2 2 1 1 true
func (Dictionary) Size ¶
func (dict Dictionary) Size() int64
Size reports the number of words there are in the Dictionary.
Time complexity: O(1)
type Directory ¶
type Directory struct {
Location string
Options DirectoryOptions
}
Directory treats a filesystem path as a collection of filesystem entries, specifically a collection of directories and files.
func (Directory) Enumerate ¶
func (d Directory) Enumerate(ctx context.Context) Enumerator[string]
Enumerate lists the items in a `Directory`
Example ¶
traverser := collection.Directory{
Location: ".",
Options: collection.DirectoryOptionsExcludeDirectories,
}
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
fileNames := collection.Select[string](traverser, path.Base)
filesOfInterest := collection.Where(fileNames, func(subject string) bool {
return subject == "filesystem_examples_test.go"
})
for entry := range filesOfInterest.Enumerate(ctx) {
fmt.Println(entry)
}
Output: filesystem_examples_test.go
type DirectoryOptions ¶
type DirectoryOptions uint
DirectoryOptions is a means of configuring a `Directory` instance to including various children in its enumeration without supplying a `Where` clause later.
type Enumerable ¶
type Enumerable[T any] interface { Enumerate(ctx context.Context) Enumerator[T] }
Enumerable offers a means of easily converting into a channel. It is most useful for types where mutability is not in question.
var Fibonacci Enumerable[uint] = fibonacciGenerator{}
Fibonacci is an Enumerable which will dynamically generate the fibonacci sequence.
func AsEnumerable ¶
func AsEnumerable[T any](entries ...T) Enumerable[T]
AsEnumerable allows for easy conversion of a slice to a re-usable Enumerable object.
func Empty ¶
func Empty[T any]() Enumerable[T]
func Merge ¶
func Merge[T any](channels ...Enumerable[T]) Enumerable[T]
Merge takes the results as it receives them from several channels and directs them into a single channel.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
a := collection.AsEnumerable(1, 2, 4)
b := collection.AsEnumerable(8, 16, 32)
c := collection.Merge(a, b)
sum := 0
for x := range c.Enumerate(ctx) {
sum += x
}
fmt.Println(sum)
product := 1
for y := range a.Enumerate(ctx) {
product *= y
}
fmt.Println(product)
Output: 63 8
func ParallelSelect ¶
func ParallelSelect[T any, E any](original Enumerable[T], operation Transform[T, E]) Enumerable[E]
ParallelSelect creates an Enumerable which will use all logically available CPUs to execute a Transform.
func Reverse ¶
func Reverse[T any](original Enumerable[T]) Enumerable[T]
Reverse will enumerate all values of an enumerable, store them in a Stack, then replay them all.
func Select ¶
func Select[T any, E any](subject Enumerable[T], transform Transform[T, E]) Enumerable[E]
Select creates a reusable stream of transformed values.
Example ¶
const offset = 'a' - 1
subject := collection.AsEnumerable[rune]('a', 'b', 'c')
subject = collection.Select(subject, func(a rune) rune {
return a - offset
})
fmt.Println(collection.ToSlice(subject))
Output: [1 2 3]
func SelectMany ¶
func SelectMany[T any, E any](subject Enumerable[T], toMany Unfolder[T, E]) Enumerable[E]
SelectMany allows for unfolding of values.
Example ¶
type BrewHouse struct {
Name string
Beers collection.Enumerable[string]
}
breweries := collection.AsEnumerable(
BrewHouse{
"Mac & Jacks",
collection.AsEnumerable(
"African Amber",
"Ibis IPA",
),
},
BrewHouse{
"Post Doc",
collection.AsEnumerable(
"Prereq Pale",
),
},
BrewHouse{
"Resonate",
collection.AsEnumerable(
"Comfortably Numb IPA",
"Lithium Altbier",
),
},
BrewHouse{
"Triplehorn",
collection.AsEnumerable(
"Samson",
"Pepper Belly",
),
},
)
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
beers := collection.SelectMany(breweries, func(brewer BrewHouse) collection.Enumerator[string] {
return brewer.Beers.Enumerate(ctx)
})
for beer := range beers.Enumerate(ctx) {
fmt.Println(beer)
}
Output: African Amber Ibis IPA Prereq Pale Comfortably Numb IPA Lithium Altbier Samson Pepper Belly
func Skip ¶
func Skip[T any](subject Enumerable[T], n uint) Enumerable[T]
Skip creates a reusable stream which will skip the first `n` elements before iterating over the rest of the elements in an Enumerable.
Example ¶
trimmed := collection.Take(collection.Skip(collection.Fibonacci, 1), 3)
for entry := range trimmed.Enumerate(context.Background()) {
fmt.Println(entry)
}
Output: 1 1 2
func Take ¶
func Take[T any](subject Enumerable[T], n uint) Enumerable[T]
Take retreives just the first `n` elements from an Enumerable.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
taken := collection.Take(collection.Fibonacci, 4)
for entry := range taken.Enumerate(ctx) {
fmt.Println(entry)
}
Output: 0 1 1 2
func TakeWhile ¶
func TakeWhile[T any](subject Enumerable[T], criteria func(T, uint) bool) Enumerable[T]
TakeWhile creates a reusable stream which will halt once some criteria is no longer met.
Example ¶
taken := collection.TakeWhile(collection.Fibonacci, func(x, n uint) bool {
return x < 10
})
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
for entry := range taken.Enumerate(ctx) {
fmt.Println(entry)
}
Output: 0 1 1 2 3 5 8
func Where ¶
func Where[T any](original Enumerable[T], p Predicate[T]) Enumerable[T]
Where creates a reusable means of filtering a stream.
Example ¶
nums := collection.EnumerableSlice[int]([]int{1, 2, 3, 4, 5})
results := collection.Where[int](nums, func(a int) bool {
return a < 3
})
fmt.Println(collection.ToSlice(results))
Output: [1 2]
type EnumerableSlice ¶
type EnumerableSlice[T any] []T
func (EnumerableSlice[T]) Enumerate ¶
func (f EnumerableSlice[T]) Enumerate(ctx context.Context) Enumerator[T]
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
// When a single value is provided, and it is an array or slice, each value in the array or slice is treated as an enumerable value.
originalInts := []int{1, 2, 3, 4, 5}
wrappedInts := collection.EnumerableSlice[int](originalInts)
for entry := range wrappedInts.Enumerate(ctx) {
fmt.Print(entry)
}
fmt.Println()
// It's easy to convert arrays to slices for these enumerations as well.
originalStrings := [7]string{"red", "orange", "yellow", "green", "blue", "indigo", "violet"}
wrappedStrings := collection.EnumerableSlice[string](originalStrings[:])
for entry := range wrappedStrings.Enumerate(ctx) {
fmt.Println(entry)
}
Output: 12345 red orange yellow green blue indigo violet
type Enumerator ¶
type Enumerator[T any] <-chan T
Enumerator exposes a new syntax for querying familiar data structures.
func (Enumerator[T]) All ¶
func (iter Enumerator[T]) All(p Predicate[T]) bool
All tests whether or not all items present meet a criteria.
func (Enumerator[T]) AsEnumerable ¶
func (iter Enumerator[T]) AsEnumerable() Enumerable[T]
AsEnumerable stores the results of an Enumerator so the results can be enumerated over repeatedly.
func (Enumerator[T]) Count ¶
func (iter Enumerator[T]) Count(p Predicate[T]) int
Count iterates over a list and keeps a running tally of the number of elements satisfy a predicate.
Example ¶
subject := collection.AsEnumerable("str1", "str1", "str2")
count1 := subject.Enumerate(context.Background()).Count(func(a string) bool {
return a == "str1"
})
fmt.Println(count1)
Output: 2
func (Enumerator[T]) CountAll ¶
func (iter Enumerator[T]) CountAll() int
CountAll iterates over a list and keeps a running tally of how many it's seen.
Example ¶
subject := collection.AsEnumerable('a', 'b', 'c', 'd', 'e')
fmt.Println(subject.Enumerate(context.Background()).CountAll())
Output: 5
func (Enumerator[T]) Discard ¶
func (iter Enumerator[T]) Discard()
Discard reads an enumerator to the end but does nothing with it. This method should be used in circumstances when it doesn't make sense to explicitly cancel the Enumeration.
func (Enumerator[T]) ElementAt ¶
func (iter Enumerator[T]) ElementAt(n uint) T
ElementAt retreives an item at a particular position in an Enumerator.
Example ¶
ctx, cancel := context.WithCancel(context.Background()) defer cancel() // ElementAt leaves the Enumerator open, creating a memory leak unless remediated, // context.Context should be cancelled to indicate that no further reads are coming. fmt.Print(collection.Fibonacci.Enumerate(ctx).ElementAt(4))
Output: 3
func (Enumerator[T]) Last ¶
func (iter Enumerator[T]) Last() (retval T)
Last retreives the item logically behind all other elements in the list.
Example ¶
subject := collection.AsEnumerable(1, 2, 3) fmt.Print(subject.Enumerate(context.Background()).Last())
Output: 3
func (Enumerator[T]) Merge ¶
func (iter Enumerator[T]) Merge(others ...Enumerator[T]) Enumerator[T]
Merge takes the results of this Enumerator and others, and funnels them into a single Enumerator. The order of in which they will be combined is non-deterministic.
func (Enumerator[T]) Reverse ¶
func (iter Enumerator[T]) Reverse() Enumerator[T]
Reverse returns items in the opposite order it encountered them in.
Example ¶
a := collection.AsEnumerable(1, 2, 3).Enumerate(context.Background()) a = a.Reverse() fmt.Println(a.ToSlice())
Output: [3 2 1]
func (Enumerator[T]) Skip ¶
func (iter Enumerator[T]) Skip(n uint) Enumerator[T]
Skip retreives all elements after the first 'n' elements.
Example ¶
subject := collection.AsEnumerable(1, 2, 3, 4, 5, 6, 7)
skipped := subject.Enumerate(context.Background()).Skip(5)
for entry := range skipped {
fmt.Println(entry)
}
Output: 6 7
func (Enumerator[T]) Take ¶
func (iter Enumerator[T]) Take(n uint) Enumerator[T]
Take retreives just the first 'n' elements from an Enumerator.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
taken := collection.Fibonacci.Enumerate(ctx).Skip(4).Take(2)
for entry := range taken {
fmt.Println(entry)
}
Output: 3 5
func (Enumerator[T]) TakeWhile ¶
func (iter Enumerator[T]) TakeWhile(criteria func(T, uint) bool) Enumerator[T]
TakeWhile continues returning items as long as 'criteria' holds true.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
taken := collection.Fibonacci.Enumerate(ctx).TakeWhile(func(x, n uint) bool {
return x < 6
})
for entry := range taken {
fmt.Println(entry)
}
Output: 0 1 1 2 3 5
func (Enumerator[T]) Tee ¶
func (iter Enumerator[T]) Tee() (Enumerator[T], Enumerator[T])
Tee creates two Enumerators which will have identical contents as one another.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
base := collection.AsEnumerable(1, 2, 4)
left, right := base.Enumerate(ctx).Tee()
var wg sync.WaitGroup
wg.Add(2)
product := 1
go func() {
for x := range left {
product *= x
}
wg.Done()
}()
sum := 0
go func() {
for x := range right {
sum += x
}
wg.Done()
}()
wg.Wait()
fmt.Printf("Sum: %d\n", sum)
fmt.Printf("Product: %d\n", product)
Output: Sum: 7 Product: 8
func (Enumerator[T]) ToSlice ¶
func (iter Enumerator[T]) ToSlice() []T
ToSlice places all iterated over values in a Slice for easy consumption.
func (Enumerator[T]) UCount ¶
func (iter Enumerator[T]) UCount(p Predicate[T]) uint
UCount iterates over a list and keeps a running tally of the number of elements satisfy a predicate.
Example ¶
subject := collection.EnumerableSlice[string]([]string{"str1", "str1", "str2"})
count1 := subject.Enumerate(context.Background()).UCount(func(a string) bool {
return a == "str1"
})
fmt.Println(count1)
Output: 2
func (Enumerator[T]) UCountAll ¶
func (iter Enumerator[T]) UCountAll() uint
UCountAll iterates over a list and keeps a running tally of how many it's seen.
Example ¶
subject := collection.EnumerableSlice[any]([]interface{}{'a', 2, "str1"})
fmt.Println(subject.Enumerate(context.Background()).UCountAll())
Output: 3
func (Enumerator[T]) Where ¶
func (iter Enumerator[T]) Where(predicate Predicate[T]) Enumerator[T]
Where iterates over a list and returns only the elements that satisfy a predicate.
Example ¶
ctx, cancel := context.WithCancel(context.Background())
defer cancel()
results := collection.Fibonacci.Enumerate(ctx).Where(func(a uint) bool {
return a > 8
}).Take(3)
fmt.Println(results.ToSlice())
Output: [13 21 34]
type LRUCache ¶
type LRUCache[K comparable, V any] struct { // contains filtered or unexported fields }
LRUCache hosts up to a given number of items. When more are presented, the least recently used item is evicted from the cache.
Example ¶
subject := collection.NewLRUCache[int, string](3) subject.Put(1, "one") subject.Put(2, "two") subject.Put(3, "three") subject.Put(4, "four") fmt.Println(subject.Get(1)) fmt.Println(subject.Get(4))
Output: false four true
func NewLRUCache ¶
func NewLRUCache[K comparable, V any](capacity uint) *LRUCache[K, V]
NewLRUCache creates an empty cache, which will accommodate the given number of items.
func (*LRUCache[K, V]) Enumerate ¶
func (lru *LRUCache[K, V]) Enumerate(ctx context.Context) Enumerator[V]
Enumerate lists each value in the cache.
Example ¶
subject := collection.NewLRUCache[int, string](3)
subject.Put(1, "one")
subject.Put(2, "two")
subject.Put(3, "three")
subject.Put(4, "four")
for key := range subject.Enumerate(context.Background()) {
fmt.Println(key)
}
Output: four three two
func (*LRUCache[K, V]) EnumerateKeys ¶
func (lru *LRUCache[K, V]) EnumerateKeys(ctx context.Context) Enumerator[K]
EnumerateKeys lists each key in the cache.
Example ¶
subject := collection.NewLRUCache[int, string](3)
subject.Put(1, "one")
subject.Put(2, "two")
subject.Put(3, "three")
subject.Put(4, "four")
for key := range subject.EnumerateKeys(context.Background()) {
fmt.Println(key)
}
Output: 4 3 2
type LinkedList ¶
type LinkedList[T any] struct { // contains filtered or unexported fields }
LinkedList encapsulates a list where each entry is aware of only the next entry in the list.
func NewLinkedList ¶
func NewLinkedList[T any](entries ...T) *LinkedList[T]
NewLinkedList instantiates a new LinkedList with the entries provided.
Example ¶
subject1 := collection.NewLinkedList('a', 'b', 'c', 'd', 'e')
fmt.Println(subject1.Length())
slice := []interface{}{1, 2, 3, 4, 5, 6}
subject2 := collection.NewLinkedList(slice...)
fmt.Println(subject2.Length())
Output: 5 6
func (*LinkedList[T]) AddBack ¶
func (list *LinkedList[T]) AddBack(entry T)
AddBack creates an entry in the LinkedList that is logically at the back of the list.
Example ¶
subject := collection.NewLinkedList(2, 3, 5) subject.AddBack(8) result, _ := subject.PeekBack() fmt.Println(result) fmt.Println(subject.Length())
Output: 8 4
func (*LinkedList[T]) AddFront ¶
func (list *LinkedList[T]) AddFront(entry T)
AddFront creates an entry in the LinkedList that is logically at the front of the list.
Example ¶
subject := collection.NewLinkedList(2, 3) subject.AddFront(1) result, _ := subject.PeekFront() fmt.Println(result)
Output: 1
func (*LinkedList[T]) Enumerate ¶
func (list *LinkedList[T]) Enumerate(ctx context.Context) Enumerator[T]
Enumerate creates a new instance of Enumerable which can be executed on.
Example ¶
subject := collection.NewLinkedList(2, 3, 5, 8)
results := collection.Select[int](subject, func(a int) int {
return -1 * a
})
for entry := range results.Enumerate(context.Background()) {
fmt.Println(entry)
}
Output: -2 -3 -5 -8
func (*LinkedList[T]) Get ¶
func (list *LinkedList[T]) Get(pos uint) (T, bool)
Get finds the value from the LinkedList. pos is expressed as a zero-based index begining from the 'front' of the list.
Example ¶
subject := collection.NewLinkedList(2, 3, 5, 8) val, _ := subject.Get(2) fmt.Println(val)
Output: 5
func (*LinkedList[T]) IsEmpty ¶
func (list *LinkedList[T]) IsEmpty() bool
IsEmpty tests the list to determine if it is populate or not.
func (*LinkedList[T]) Length ¶
func (list *LinkedList[T]) Length() uint
Length returns the number of elements present in the LinkedList.
func (*LinkedList[T]) PeekBack ¶
func (list *LinkedList[T]) PeekBack() (T, bool)
PeekBack returns the entry logicall stored at the back of the list without removing it.
func (*LinkedList[T]) PeekFront ¶
func (list *LinkedList[T]) PeekFront() (T, bool)
PeekFront returns the entry logically stored at the front of this list without removing it.
func (*LinkedList[T]) RemoveBack ¶
func (list *LinkedList[T]) RemoveBack() (T, bool)
RemoveBack returns the entry logically stored at the back of this list and removes it.
func (*LinkedList[T]) RemoveFront ¶
func (list *LinkedList[T]) RemoveFront() (T, bool)
RemoveFront returns the entry logically stored at the front of this list and removes it.
func (*LinkedList[T]) Sort ¶
func (list *LinkedList[T]) Sort(comparator Comparator[T]) error
Sort rearranges the positions of the entries in this list so that they are ascending.
Example ¶
// Sorti sorts into ascending order, this example demonstrates sorting
// into descending order.
subject := collection.NewLinkedList(2, 4, 3, 5, 7, 7)
subject.Sort(func(a, b int) (int, error) {
return b - a, nil
})
fmt.Println(subject)
Output: [7 7 5 4 3 2]
func (*LinkedList[T]) String ¶
func (list *LinkedList[T]) String() string
String prints upto the first fifteen elements of the list in string format.
Example ¶
subject1 := collection.NewLinkedList[int]()
for i := 0; i < 20; i++ {
subject1.AddBack(i)
}
fmt.Println(subject1)
subject2 := collection.NewLinkedList[int](1, 2, 3)
fmt.Println(subject2)
Output: [0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 ...] [1 2 3]
func (*LinkedList[T]) Swap ¶
func (list *LinkedList[T]) Swap(x, y uint) error
Swap switches the positions in which two values are stored in this list. x and y represent the indexes of the items that should be swapped.
Example ¶
subject := collection.NewLinkedList(2, 3, 5, 8, 13) subject.Swap(1, 3) fmt.Println(subject)
Output: [2 8 5 3 13]
func (*LinkedList[T]) ToSlice ¶
func (list *LinkedList[T]) ToSlice() []T
ToSlice converts the contents of the LinkedList into a slice.
type List ¶
type List[T any] struct { // contains filtered or unexported fields }
List is a dynamically sized list akin to List in the .NET world, ArrayList in the Java world, or vector in the C++ world.
func (*List[T]) Add ¶
func (l *List[T]) Add(entries ...T)
Add appends an entry to the logical end of the List.
func (*List[T]) AddAt ¶
AddAt injects values beginning at `pos`. If multiple values are provided in `entries` they are placed in the same order they are provided.
Example ¶
subject := NewList(0, 1, 4, 5, 6) subject.AddAt(2, 2, 3) fmt.Println(subject)
Output: [0 1 2 3 4 5 6]
func (*List[T]) Enumerate ¶
func (l *List[T]) Enumerate(ctx context.Context) Enumerator[T]
Enumerate lists each element present in the collection
func (*List[T]) Get ¶
Get retreives the value stored in a particular position of the list. If no item exists at the given position, the second parameter will be returned as false.
type Queue ¶
type Queue[T any] struct { // contains filtered or unexported fields }
Queue implements a basic FIFO structure.
func NewQueue ¶
NewQueue instantiates a new FIFO structure.
Example ¶
empty := NewQueue[int]() fmt.Println(empty.Length()) populated := NewQueue(1, 2, 3, 5, 8, 13) fmt.Println(populated.Length())
Output: 0 6
func (*Queue[T]) Add ¶
func (q *Queue[T]) Add(entry T)
Add places an item at the back of the Queue.
Example ¶
subject := &Queue[int]{}
subject.Add(1)
subject.Add(2)
res, _ := subject.Peek()
fmt.Println(res)
Output: 1
func (*Queue[T]) Enumerate ¶
func (q *Queue[T]) Enumerate(ctx context.Context) Enumerator[T]
Enumerate peeks at each element of this queue without mutating it.
func (*Queue[T]) IsEmpty ¶
IsEmpty tests the Queue to determine if it is populate or not.
Example ¶
empty := NewQueue[int]() fmt.Println(empty.IsEmpty()) populated := NewQueue(1, 2, 3, 5, 8, 13) fmt.Println(populated.IsEmpty())
Output: true false
func (*Queue[T]) Next ¶
Next removes and returns the next item in the Queue.
Example ¶
subject := NewQueue(1, 2, 3, 5, 8, 13)
for !subject.IsEmpty() {
val, _ := subject.Next()
fmt.Println(val)
}
Output: 1 2 3 5 8 13
type Stack ¶
type Stack[T any] struct { // contains filtered or unexported fields }
Stack implements a basic FILO structure.
func NewStack ¶
NewStack instantiates a new FILO structure.
Example ¶
subject := NewStack(1, 2, 3)
for !subject.IsEmpty() {
val, _ := subject.Pop()
fmt.Println(val)
}
Output: 3 2 1
func (*Stack[T]) Enumerate ¶
func (stack *Stack[T]) Enumerate(ctx context.Context) Enumerator[T]
Enumerate peeks at each element in the stack without mutating it.
type Transform ¶
Transform defines a function which takes a value, and returns some value based on the original.
type Unfolder ¶
type Unfolder[T any, E any] func(T) Enumerator[E]
Unfolder defines a function which takes a single value, and exposes many of them as an Enumerator