gog

package module
v0.13.1 Latest Latest
Warning

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

Go to latest
Published: Apr 3, 2024 License: MIT Imports: 1 Imported by: 4

README

GoG (Go Generics)

Go Reference Go Report Card

GoG is a Go library with useful generic functions and types.

Since the introduction of generics in Go 1.18, a number of useful and reusable data structures, algorithms and utility functions are now possible. This library attempts to cover some of the most common use cases.

It avoids duplicating functions that are already provided by slices and maps.

For a complete list on available functions and types, check the godoc documentation for this project:

Examples

Converting slice values from one type to another:

source := []int{1, 2, 3, 4}
target := gog.Map(source, func(item int) float64 {
  return float64(item) / 2.0
})
// target = []float64{0.5, 1.0, 1.5, 2.0}

Removing duplicate items in a slice:

source := []string{"john", "bill", "eric", "john", "max", "eric"}
target := gog.Dedupe(source)
// target = []string{"john", "bill", "eric", "max"}

Finding an item in a slice:

source := []string{"user 01", "user 02", "user 05", "user 33"}
foundItem, ok := gog.FindFunc(source, func(item string) bool {
  return strings.Contains(item, "02")
})
// ok = true
// foundItem = "user 02"

Selecting specific slice items:

source := []int{1, 2, 3, 4}
target := gog.Select(source, func(item int) bool {
  return item % 2 == 0
})
// target = []int{2, 4}

Documentation

Overview

Package gog provides utilities for working with Go generics.

This top-level package contains common functions that transform, search and filter built-in Go types (e.g. slices, maps, etc) of generic type.

For more sophisticated scenarios check subdirectories.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func Concat deprecated added in v0.10.0

func Concat[T any](slices ...[]T) []T

Concat takes a series of slices and concatenates them into one single slice.

This function always allocates a brand new slice with appropriate capacity and never mutates any of the passed slices.

Deprecated: Use built-in slices.Concat instead.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	first := []int{1, 2}
	second := []int{3, 4}
	result := gog.Concat(first, second)
	fmt.Printf("%#v\n", result)

}
Output:

[]int{1, 2, 3, 4}

func Dedupe added in v0.2.0

func Dedupe[T comparable](slice []T) []T

Dedupe returns a new slice that contains only distinct elements from the original slice.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{1, 1, 2, 3, 3, 4}
	target := gog.Dedupe(source)
	fmt.Printf("%#v\n", target)

}
Output:

[]int{1, 2, 3, 4}

func DerefElements added in v0.9.0

func DerefElements[T any](slice []*T) []T

DerefElements converts a slice of element pointers into a slice of those elements.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	first, second, third := "first", "second", "third"
	source := []*string{&first, &second, &third}
	target := gog.DerefElements(source)
	fmt.Printf("%#v\n", target)

}
Output:

[]string{"first", "second", "third"}

func FindFunc added in v0.7.0

func FindFunc[T any](slice []T, fn func(e T) bool) (T, bool)

FindFunc iterates over the slice and uses the provided closure function to check whether the elements match a user-provided condition. The first value that matches is returned as well as a true flag. Otherwise a false flag is returned.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/mokiat/gog"
)

func main() {
	source := []string{"user 01", "user 02", "user 03"}
	target, ok := gog.FindFunc(source, func(item string) bool {
		return strings.Contains(item, "02")
	})
	fmt.Println(ok)
	fmt.Println(target)

}
Output:

true
user 02

func FindFuncPtr added in v0.7.0

func FindFuncPtr[T any](slice []T, fn func(e T) bool) *T

FindFuncPtr iterates over the slice and uses the provided closure function to check whether the elements match a user-provided condition. A pointer to the first element that passes the condition is returned. If no value is applicable, then nil is returned.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/mokiat/gog"
)

func main() {
	source := []string{"user 01", "user 02", "user 03"}
	target := gog.FindFuncPtr(source, func(item string) bool {
		return strings.Contains(item, "02")
	})
	fmt.Println(target != nil)
	fmt.Println(*target)
	*target = "user 04"
	fmt.Printf("%#v\n", source)

}
Output:

true
user 02
[]string{"user 01", "user 04", "user 03"}

func Flatten added in v0.3.0

func Flatten[T any](slice [][]T) []T

Flatten returns a new slice that is the result of merging all nested slices into a single top-level slice.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := [][]int{
		{1, 2, 3},
		{4, 5, 6, 7},
	}
	target := gog.Flatten(source)
	fmt.Printf("%#v\n", target)

}
Output:

[]int{1, 2, 3, 4, 5, 6, 7}

func Map

func Map[S, T any](slice []S, fn func(S) T) []T

Map can be used to transform one slice into another by providing a function to do the mapping.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{1, 2, 3}
	target := gog.Map(source, func(item int) string {
		return strconv.Itoa(item * 2)
	})
	fmt.Printf("%#v\n", target)

}
Output:

[]string{"2", "4", "6"}

func MapIndex added in v0.12.0

func MapIndex[S, T any](slice []S, fn func(int, S) T) []T

MapIndex is similar to Map, except that it passes the element index to the closure function as well.

func Mapping added in v0.3.0

func Mapping[S any, K comparable, V any](slice []S, fn func(S) (K, V)) map[K][]V

Mapping is similar to Partition, except that it allows one to transform the values stored in the partition buckets. In essence, it allows the caller to construct an almost arbitrary map (it is always of kind map[key][]value, though the types of the keys and the values are user controlled) from an arbitrary slice.

Example
package main

import (
	"fmt"
	"strconv"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{1, 2, 3, 4, 5}
	target := gog.Mapping(source, func(item int) (bool, string) {
		isEven := item%2 == 0
		return isEven, strconv.Itoa(item)
	})
	fmt.Printf("even: %#v\n", target[true])
	fmt.Printf("odd: %#v\n", target[false])

}
Output:

even: []string{"2", "4"}
odd: []string{"1", "3", "5"}

func Merge added in v0.10.0

func Merge[K comparable, V any](ms ...map[K]V) map[K]V

Merge takes a series of maps and merges them into a single map.

If there are overlapping keys, then latter maps overwrite former maps.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	first := map[int]string{
		1: "odd",
		2: "even",
	}
	second := map[int]string{
		1:     "small",
		10000: "large",
	}
	result := gog.Merge(first, second)

	fmt.Printf("1: %#v\n", result[1])
	fmt.Printf("2: %#v\n", result[2])
	fmt.Printf("10000: %#v\n", result[10000])

}
Output:

1: "small"
2: "even"
10000: "large"

func Mutate added in v0.7.0

func Mutate[T any](slice []T, fn func(e *T))

Mutate iterates over the slice and calls the provided closure function, passing a pointer to each element. This allows the user to easily modify all the elements of a slice.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{1, 2, 3, 4, 5}
	gog.Mutate(source, func(item *int) {
		*item = *item + 10
	})
	fmt.Printf("%#v\n", source)

}
Output:

[]int{11, 12, 13, 14, 15}

func MutateIndex added in v0.12.0

func MutateIndex[T any](slice []T, fn func(index int, e *T))

MutateIndex is similar to Mutate, except that it passes the element index to the closure function as well.

func Partition

func Partition[S any, K comparable](slice []S, fn func(S) K) map[K][]S

Partition splits the specified slice into groups, each having a key according to the specified function.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{1, 2, 3, 4, 5}
	target := gog.Partition(source, func(item int) bool {
		isEven := item%2 == 0
		return isEven
	})
	fmt.Printf("even: %#v\n", target[true])
	fmt.Printf("odd: %#v\n", target[false])

}
Output:

even: []int{2, 4}
odd: []int{1, 3, 5}

func PtrOf

func PtrOf[T any](v T) *T

PtrOf returns a pointer to the passed value.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	ptr := gog.PtrOf("hello world") // since &"hello world" is not possible
	fmt.Println(ptr != nil)
	fmt.Println(*ptr)

}
Output:

true
hello world

func Reduce

func Reduce[S, T any](slice []S, initialValue T, fn func(accum T, value S) T) T

Reduce compacts a slice into a single value. The provided function is used to perform the reduction starting with the initialValue.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{2, 30, 100}
	target := gog.Reduce(source, 0, func(accum, item int) int {
		return accum + item*2
	})
	fmt.Println(target)

}
Output:

264

func RefElements added in v0.9.0

func RefElements[T any](slice []T) []*T

RefElements converts a slice of elements into a slice of pointers to those same elements.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{5, 7}
	target := gog.RefElements(source)
	*target[0] = 9
	*target[1] = 11
	fmt.Printf("%#v\n", source)

}
Output:

[]int{9, 11}

func Select

func Select[S any](slice []S, fn func(S) bool) []S

Select returns a new slice that contains only the elements of the original slice that pass the filter function.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	source := []int{5, 8, 9, 10}
	target := gog.Select(source, func(item int) bool {
		isEven := item%2 == 0
		return isEven
	})
	fmt.Printf("%#v\n", target)

}
Output:

[]int{8, 10}

func ValueOf

func ValueOf[T any](v *T, defaultValue T) T

ValueOf is the opposite of PtrOf. It takes a pointer an dereferences it. If the pointer is nil, then it uses the provided defaultValue.

Example
package main

import (
	"fmt"

	"github.com/mokiat/gog"
)

func main() {
	firstValue := "first"

	var firstPtr *string = &firstValue
	var secondPtr *string = nil

	first := gog.ValueOf(firstPtr, "default")
	fmt.Println(first)

	second := gog.ValueOf(secondPtr, "default")
	fmt.Println(second)

}
Output:

first
default

func Zero added in v0.12.0

func Zero[T any]() T

Zero returns the zero value of the generic type T.

Types

type KV added in v0.3.0

type KV[K comparable, V any] struct {
	// Key holds the key of this key-value pair.
	Key K

	// Value holds the value of this key-value pair.
	Value V
}

KV represents a key-value pair.

func Entries added in v0.3.0

func Entries[K comparable, V any](m map[K]V) []KV[K, V]

Entries returns a slice of key-value pair mappings that make up the specified map.

Note: There is no guarantee as to the order of the returned entries, nor is that order guaranteed to be consistent across two calls.

Example
package main

import (
	"fmt"
	"slices"

	"github.com/mokiat/gog"
)

func main() {
	source := map[string][]int{
		"even": {2, 4, 6},
		"odd":  {1, 3, 5},
	}
	target := gog.Entries(source)
	slices.SortFunc(target, func(first, second gog.KV[string, []int]) int {
		switch {
		case first.Key < second.Key:
			return -1
		case first.Key > second.Key:
			return 1
		default:
			return 0
		}
	})
	fmt.Printf("%+v\n", target)

}
Output:

[{Key:even Value:[2 4 6]} {Key:odd Value:[1 3 5]}]

Directories

Path Synopsis
Package ds provides various data structure implementations with generics.
Package ds provides various data structure implementations with generics.
Package filter adds helper functions for performing filtering over a data set.
Package filter adds helper functions for performing filtering over a data set.
Package opt provides utilities for representing optional types.
Package opt provides utilities for representing optional types.

Jump to

Keyboard shortcuts

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