slt

package module
v0.0.0-...-d7985c2 Latest Latest
Warning

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

Go to latest
Published: Feb 21, 2024 License: MIT Imports: 1 Imported by: 0

README

Slice Tools

Go Reference

Some simple functions to work with slices. Functions in the official slices are not part of this small library.

NOTE: These implementations are not optimized.

What does this library bring to the table?

  • All / Every: Checks if all entries pass the provided function.
  • Any / Some: Checks if at least one entry passes the provided function.
  • Count: Counts all entries that pass the provided function.
  • Diff: Return the elements that are in only one of two slices.
  • Find: Find returns the first element that match the predicate.
  • GroupBy: Creates a map of slices, grouped by the provided function.
  • Intersect: Takes 2 slices and returns a new slice containing overlapping elements.
  • Map: Creates a new slice based on the provided function.
  • None: Checks if no entry passes the provided function.
  • Overlap / OverlapFunc: Checks if two slices have overlapping entries.
  • Reduce: Loops all entries and returns a new value.
  • Reject: Removes all entries that pass the provided function. (This is similiar to slices.DeleteFunc, but it doesn't change the original slice.)
  • Remove: Remove certain elements from a slice. (slices.Delete uses an index, this uses values).
  • Select: Keeps all entries that pass the provided function.
  • SplitBy: Splits a slice into 2 parts using the provided function.
  • Union: Merge all slices and remove duplicates.
  • Unique / UniqueFunc: Removed duplicates from the slice.

Aside from that there are some functions for numbers:

  • Between: Check if Number is between two values. [Curried Function]
  • Even: Check if an Integer is dividable by 2.
  • Greater: Check if a Number is greater than a certain value. [Curried Function]
  • Less: Check if a Number is below a certain value. [Curried Function]
  • Odd: Check if an Integer is NOT dividable by 2.

Examples

For the sake of keeping things short, the following code is assumed in all cases:

type Person struct {
    Name string
    Age  int
}

type Hero struct {
    Name     string
    Universe string
}

func isMinor(person Person) bool {
    return person.Age < 18
}

var (
    viewers = []Person{
        { Name: "Chris", Age: 38 },
        { Name: "Danny", Age: 21 },
        { Name: "Betty", Age: 30 },
        { Name: "Karen", Age: 55 },
        { Name: "Peter", Age: 17 },
    }

    roomA = []string{
        "Betty", "Chris", "Danny", "Peter",
    }

    roomB = []string{
        "Betty", "Danny", "Karen", "Peter",
    }

    heroes = []Hero{
        { Name: "Batman", Universe: "DC" },
        { Name: "Captain America", Universe: "Marvel" },
        { Name: "Flash", Universe: "DC" },
        { Name: "Hulk", Universe: "Marvel" },
        { Name: "Iron Man", Universe: "Marvel" },
        { Name: "Robin", Universe "DC" },
        { Name: "Superman", Universe: "DC" },
        { Name: "Thor", Universe: "Marvel" },
    }
)
All / Every

The function "All" loops through all entries of a given slice and executes the provided callback on every element. That is, until the callback returns false or there are no more entries to check.

The function "Every" is simply an alias to "All" and works the same way.

func main() {
    // This returns false right at the first entry "Chris"
    if slt.All(viewers, isMinor) == false {
        fmt.Println("Not all viewers are minors!")
    }
}
Any / Some

The function "Any" loops through all entries of a given slice and executes the provided callback on every element. That is, until the callback returns true or there are no more entries to check.

The function "Some" is simply an alias to "Any" and works the same way.

func main() {
    // This returns true at the last entry "Peter".
    if slt.Any(viewers, isMinor) == false {
        fmt.Println("At least one viewer is a minor!")
    }
}
Count

The function "Count" loops through all entries of a given slice and executes the provided callback on every element. It counts all entries that return true.

func main() {
    fmt.Printf("There are %d minor viewer(s).", slt.Count(viewers, isMinor))

    // Output:
    // There are 1 minor viewer(s).
}
Diff

The function "Diff" takes two slices of the same type and returns the elements that appear only in one of the slices.

func main() {
    fmt.Println(slt.Diff(roomA, roomB))

    // Output:
    // - Chris
    // - Karen
}
Find

The function "Find" takes a slice, an offset and a predicate. It returns the first element - and it's index - in the slice that matches the predicate. If there are no elements that match, the default value for that datatype and -1 for the index are returned.

This functions is less useful when using primitive types. For this, the slices.Index would be more useful.

func main() {
    someone, index := slt.Find(room, 0, func(person Person) bool {
        return !isMinor(person)
    })

    fmt.Printf("The first person of age in the room is %s at position %d", someone.Name, index)

    // Output:
    // The first person of age in the room is Chris at position 0
}
GroupBy

The function "GroupBy" creates a map based on the result of the callback. This can be used to group a slice into multiple sub-slices.

func main() {
    byUniverse := func(hero Hero) string {
        return hero.Universe
    }

    grouped := slt.GroupBy(heroes, byUniverse)
	for universe, heroes := range grouped {
		fmt.Printf("Universe: %v\n", universe)
		fmt.Printf("%+v\n", heroes)
	}

    // Output:
    // Universe: DC
    // [{Name:Batman Universe:DC} {Name:Flash Universe:DC} {Name:Robin Universe:DC} {Name:Superman Universe:DC}]
    // Universe: Marvel
    // [{Name:Captain America Universe:Marvel} {Name:Hulk Universe:Marvel} {Name:Iron Man Universe:Marvel} {Name:Thor Universe:Marvel}]
}

Documentation

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

func All

func All[S ~[]E, E any](s S, fn func(E) bool) bool

All checks if every entry in the slice match the predicate.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println(slt.All(input, numbers.Even))
	fmt.Println(slt.All(input, numbers.Below(10, true)))
}
Output:

false
true

func Any

func Any[S ~[]E, E any](s S, fn func(E) bool) bool

Any checks if there is at least one entry that match the predicate.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println(slt.Any(input, numbers.Even))
	fmt.Println(slt.All(input, numbers.Above(10, true)))
}
Output:

true
false

func Count

func Count[S ~[]E, E any](s S, fn func(E) bool) int

Count counts the entries that match the predicate

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println(slt.Count(input, numbers.Even))
	fmt.Println(slt.Count(input, numbers.Above(8, true)))
}
Output:

5
2

func Diff

func Diff[S ~[]E, E comparable](a S, b S) S

Diff returns the elements that are only in one of the slices.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	sliceA := []string{"A", "B", "C", "D"}
	sliceB := []string{"A", "G", "B", "F"}
	diff := slt.Diff(sliceA, sliceB)

	fmt.Println(diff)
}
Output:

[C D G F]

func Every

func Every[S ~[]E, E any](s S, fn func(E) bool) bool

Every is an alias for All.

func Find

func Find[S ~[]E, E any](s S, offset int, f func(E) bool) (E, int)

Find returns the first element that match the predicate. It also returns the index. In case no element matches, an empty value and -1 are returned.

If the offset is less than zero, it defaults to zero.

Example
package main

import (
	"fmt"
	"strings"

	"github.com/christopher-kleine/slt"
)

func main() {
	input := []string{"Anna", "Berta", "chris"}
	isLowerCase := func(s string) bool {
		return strings.ToLower(s) == s
	}
	lowerCaseEntry, index := slt.Find(input, 0, isLowerCase)
	if index > -1 {
		fmt.Println("Found the lower case word entry:", lowerCaseEntry)
	} else {
		fmt.Println("No word is purely lowercase")
	}

	input = []string{"Anna", "Berta", "Chris"}
	lowerCaseEntry, index = slt.Find(input, 0, isLowerCase)
	if index > -1 {
		fmt.Println("Found the lower case word entry:", lowerCaseEntry)
	} else {
		fmt.Println("No word is purely lowercase")
	}
}
Output:

Found the lower case word entry: chris
No word is purely lowercase

func GroupBy

func GroupBy[S ~[]E, E any, T comparable](s S, fn func(E) T) map[T]S

GroupBy uses the callback to group the provided slice into a map of slices.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	toWord := func(v int) string {
		if v%2 == 0 {
			return "Even"
		} else {
			return "Odd"
		}
	}
	fmt.Println(slt.GroupBy(input, toWord))
}
Output:

map[Even:[0 2 4 6 8] Odd:[1 3 5 7 9]]

func Intersect

func Intersect[S ~[]E, E comparable](a S, b S) S

Intersect returns the elements that are in both slices.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	sliceA := []string{"A", "B", "C", "D"}
	sliceB := []string{"A", "G", "B", "F"}
	diff := slt.Intersect(sliceA, sliceB)

	fmt.Println(diff)
}
Output:

[A B]

func Map

func Map[S ~[]E, E any, T any](s S, fn func(E) T) []T

Map applies a transform function on all entries in a slice and returns the new slice.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	toWord := func(v int) string {
		if v%2 == 0 {
			return "Even"
		} else {
			return "Odd"
		}
	}
	fmt.Println(slt.Map(input, toWord))
}
Output:

[Even Odd Even Odd Even Odd Even Odd Even Odd]

func None

func None[S ~[]E, E any](s S, f func(E) bool) bool

None checks if no entry that match the predicate. It's the opposite of Any/Some.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println(slt.None(input, numbers.Even))
	fmt.Println(slt.None(input, numbers.Below(10, true)))
}
Output:

false
false

func Overlap

func Overlap[S ~[]E, E comparable](a S, b S) bool

Overlap checks if any value in slice A is also found in slice B.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	ListA := []int{1, 2, 3}
	ListB := []int{1, 5, 7}
	ListC := []int{5, 7, 9}

	fmt.Println(slt.Overlap(ListA, ListB))
	fmt.Println(slt.Overlap(ListA, ListC))
}
Output:

true
false

func OverlapFunc

func OverlapFunc[S ~[]E, E any](a S, b S, fn func(E, E) bool) bool

OverlapFunc checks if any value in slice A is also found in slice B.

func Reduce

func Reduce[S ~[]E, E any](s S, start E, f func(acc E, curr E) E) E

Reduce reduces a collection using the function fn

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
	add := func(acc int, curr int) int {
		return acc + curr
	}
	fmt.Println("Sum of all numbers between 1 and 10 is:", slt.Reduce(numbers, 0, add))
}
Output:

Sum of all numbers between 1 and 10 is: 55

func Reject

func Reject[S ~[]E, E any](s S, f func(E) bool) S

Reject returns a new slice, removing all elements using the predicate.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println("Even Numbers:", slt.Reject(input, numbers.Even))
}
Output:

Even Numbers: [1 3 5 7 9]

func Remove

func Remove[S ~[]E, E comparable](s S, e ...E) S

Remove values from a slice.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	input := []string{"H", "E", "L", "L", "O", "W", "O", "R", "L", "D"}
	removed := slt.Remove(input, "A", "E", "I", "O", "U")
	fmt.Println(removed)
}
Output:

[H L L W R L D]

func Select

func Select[S ~[]E, E any](s S, f func(E) bool) S

Select filters the given slice by using the predicate.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	fmt.Println("Even Numbers:", slt.Select(input, numbers.Even))
}
Output:

Even Numbers: [0 2 4 6 8]

func Some

func Some[S ~[]E, E any](s S, fn func(E) bool) bool

Some is an alias for Any.

func SplitBy

func SplitBy[S ~[]E, E any](s S, f func(E) bool) (S, S)

SplitBy splits the slice into 2 parts and returns them.

The first slice is the result of every entry that match the predicate.

The second slice is the result of every entry that failed the predicate.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
	"github.com/christopher-kleine/slt/numbers"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
	even, odd := slt.SplitBy(input, numbers.Even)
	fmt.Println(even)
	fmt.Println(odd)
}
Output:

[0 2 4 6 8]
[1 3 5 7 9]

func Union

func Union[S ~[]E, E comparable](s ...S) S

Union takes a number of slices and combines them into one. The difference between Union and the built-in function append lies in the removal of duplicates.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	a := []string{"A", "B", "C", "D", "H"}
	b := []string{"A", "C", "E", "F", "G"}
	c := []string{"F", "G", "I", "J", "K"}
	d := slt.Union(a, b, c)

	fmt.Println(d)
}
Output:

[A B C D H E F G I J K]

func Unique

func Unique[S ~[]E, E comparable](s S) S

Unique makes sure every entry only appears once. It won't change the order of entries.

Example
package main

import (
	"fmt"

	"github.com/christopher-kleine/slt"
)

func main() {
	input := []int{0, 1, 2, 3, 4, 5, 6, 5, 1}
	fmt.Println(slt.Unique(input))
}
Output:

[0 1 2 3 4 5 6]

func UniqueFunc

func UniqueFunc[S ~[]E, E any](s S, cmp func(a, b E) int) S

UniqueFunc makes sure every entry only appears once. Unlike Unique this changes the order of entries.

Types

This section is empty.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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