filter

package module
v0.6.1 Latest Latest
Warning

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

Go to latest
Published: May 25, 2026 License: Apache-2.0 Imports: 2 Imported by: 2

README

Filter Package

A Go package providing generic filtering utilities for maps and slices with various logical operations.

Features

  • Filter maps and slices with simple predicates
  • Combine multiple filters with logical operations (AND, OR, NOT AND, NOT OR)
  • Select elements from slices (first, last, random)
  • Convert slices to filter functions
  • Type-safe operations using Go generics

Installation

go get github.com/dioad/filter

Usage

Filtering Slices
package main

import (
    "fmt"
    "github.com/dioad/filter"
)

func main() {
    // Basic filtering
    numbers := []int{1, 2, 3, 4, 5}
    
    // Filter even numbers
    isEven := func(n int) bool {
        return n%2 == 0
    }
    
    evenNumbers := filter.FilterSlice(numbers, isEven)
    fmt.Println(evenNumbers) // Output: [2 4]
    
    // Combining filters with AND
    isGreaterThanThree := func(n int) bool {
        return n > 3
    }
    
    evenAndGreaterThanThree := filter.FilterSliceAnd(numbers, isEven, isGreaterThanThree)
    fmt.Println(evenAndGreaterThanThree) // Output: [4]
    
    // Combining filters with OR
    isLessThanTwo := func(n int) bool {
        return n < 2
    }
    
    evenOrLessThanTwo := filter.FilterSliceOr(numbers, isEven, isLessThanTwo)
    fmt.Println(evenOrLessThanTwo) // Output: [1, 2, 4]
}
Filtering Maps
package main

import (
    "fmt"
    "github.com/dioad/filter"
)

func main() {
    // Map filtering
    users := map[string]int{
        "Alice": 25,
        "Bob":   30,
        "Carol": 22,
        "Dave":  35,
    }
    
    // Filter users older than 25
    isOlderThan25 := func(age int) bool {
        return age > 25
    }
    
    olderUsers := filter.FilterMap(users, isOlderThan25)
    fmt.Println(olderUsers) // Output: map[Bob:30 Dave:35]
}
Selecting Elements from Slices
package main

import (
    "fmt"
    "github.com/dioad/filter"
)

func main() {
    fruits := []string{"apple", "banana", "cherry", "date"}
    
    // Select first element
    first := filter.SliceSelectFirst(fruits)
    fmt.Println(*first) // Output: apple
    
    // Select last element
    last := filter.SliceSelectLast(fruits)
    fmt.Println(*last) // Output: date
    
    // Select random element
    random := filter.SliceSelectRandom(fruits)
    fmt.Println(*random) // Output: (random fruit)
}

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

License

This project is licensed under the Apache License, Version 2.0 - see the LICENSE file for details.

Documentation

Overview

Package filter provides generic filtering utilities for maps and slices with various logical operations.

The package is designed to make filtering operations on collections more concise and readable by providing a set of utility functions that can be combined to create complex filtering logic.

Key features:

- Filter maps and slices with simple predicates - Combine multiple filters with logical operations (AND, OR, NOT AND, NOT OR) - Select elements from slices (first, last, random) - Convert slices to filter functions - Type-safe operations using Go generics

Example usage for filtering slices:

numbers := []int{1, 2, 3, 4, 5}

// Filter even numbers
isEven := func(n int) bool {
    return n%2 == 0
}

evenNumbers := filter.FilterSlice(numbers, isEven)
// evenNumbers = [2, 4]

Example usage for filtering maps:

users := map[string]int{
    "Alice": 25,
    "Bob":   30,
    "Carol": 22,
    "Dave":  35,
}

// Filter users older than 25
isOlderThan25 := func(age int) bool {
    return age > 25
}

olderUsers := filter.FilterMap(users, isOlderThan25)
// olderUsers = map[Bob:30 Dave:35]

For more examples and detailed documentation, see the README.md file.

Example (CombiningFilters)
package main

import (
	"fmt"

	"github.com/dioad/filter"
)

func main() {
	// Creating reusable filters
	isEven := func(n int) bool { return n%2 == 0 }
	isPositive := func(n int) bool { return n > 0 }
	isGreaterThan10 := func(n int) bool { return n > 10 }

	// Combining filters with logical operations
	isEvenAndPositive := filter.And(isEven, isPositive)
	isEvenOrGreaterThan10 := filter.Or(isEven, isGreaterThan10)
	isNotEvenAndNotPositive := filter.NotAnd(isEven, isPositive)

	numbers := []int{-4, -3, -2, -1, 0, 1, 2, 3, 4, 11, 12}

	// Apply the combined filters
	evenAndPositive := filter.FilterSlice(numbers, isEvenAndPositive)
	evenOrGreaterThan10 := filter.FilterSlice(numbers, isEvenOrGreaterThan10)
	notEvenAndNotPositive := filter.FilterSlice(numbers, isNotEvenAndNotPositive)

	fmt.Println("Even and positive:", evenAndPositive)
	fmt.Println("Even or greater than 10:", evenOrGreaterThan10)
	fmt.Println("Not (even and positive):", notEvenAndNotPositive)

}
Output:
Even and positive: [2 4 12]
Even or greater than 10: [-4 -2 0 2 4 11 12]
Not (even and positive): [-4 -3 -2 -1 0 1 3 11]
Example (ConvertingSlicesToFilters)
package main

import (
	"fmt"

	"github.com/dioad/filter"
)

func main() {
	// Define a list of allowed values
	allowedIDs := []int{1, 3, 5}

	// Convert the slice to a filter function
	hasAllowedID := filter.SliceToOrFilter(allowedIDs, func(id int) func(int) bool {
		return filter.Equals(id)
	})

	// Apply the filter to a list of IDs
	allIDs := []int{1, 2, 3, 4, 5, 6}
	filteredIDs := filter.FilterSlice(allIDs, hasAllowedID)

	fmt.Println("Allowed IDs:", filteredIDs)

}
Output:
Allowed IDs: [1 3 5]
Example (FilteringMaps)
package main

import (
	"fmt"

	"github.com/dioad/filter"
)

func main() {
	// Map filtering
	users := map[string]int{
		"Alice": 25,
		"Bob":   30,
		"Carol": 22,
		"Dave":  35,
	}

	// Filter users older than 25
	isOlderThan25 := func(age int) bool {
		return age > 25
	}

	olderUsers := filter.FilterMap(users, isOlderThan25)
	fmt.Println("Users older than 25:", olderUsers)

	// Filter users younger than 30 and older than 20
	isYoungerThan30 := func(age int) bool {
		return age < 30
	}
	isOlderThan20 := func(age int) bool {
		return age > 20
	}

	middleAgedUsers := filter.FilterMapAnd(users, isYoungerThan30, isOlderThan20)
	fmt.Println("Users between 20 and 30:", middleAgedUsers)

}
Output:
Users older than 25: map[Bob:30 Dave:35]
Users between 20 and 30: map[Alice:25 Carol:22]
Example (FilteringSlices)
package main

import (
	"fmt"

	"github.com/dioad/filter"
)

func main() {
	// Basic filtering
	numbers := []int{1, 2, 3, 4, 5}

	// Filter even numbers
	isEven := func(n int) bool {
		return n%2 == 0
	}

	evenNumbers := filter.FilterSlice(numbers, isEven)
	fmt.Println("Even numbers:", evenNumbers)

	// Combining filters with AND
	isGreaterThanThree := func(n int) bool {
		return n > 3
	}

	evenAndGreaterThanThree := filter.FilterSliceAnd(numbers, isEven, isGreaterThanThree)
	fmt.Println("Even and greater than 3:", evenAndGreaterThanThree)

	// Combining filters with OR
	isLessThanTwo := func(n int) bool {
		return n < 2
	}

	evenOrLessThanTwo := filter.FilterSliceOr(numbers, isEven, isLessThanTwo)
	fmt.Println("Even or less than 2:", evenOrLessThanTwo)

}
Output:
Even numbers: [2 4]
Even and greater than 3: [4]
Even or less than 2: [1 2 4]
Example (SelectingFromSlices)
package main

import (
	"fmt"

	"github.com/dioad/filter"
)

func main() {
	fruits := []string{"apple", "banana", "cherry", "date"}

	// Select first element
	first := filter.SliceSelectFirst(fruits)
	fmt.Println("First fruit:", *first)

	// Select last element
	last := filter.SliceSelectLast(fruits)
	fmt.Println("Last fruit:", *last)

	// Select a specific element using filtering
	cherries := filter.FilterSlice(fruits, filter.Equals("cherry"))
	cherry, err := filter.OneOnly(cherries)
	if err == nil {
		fmt.Println("Found cherry:", *cherry)
	}

}
Output:
First fruit: apple
Last fruit: date
Found cherry: cherry

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoElement is returned when an operation expects at least one element but the slice is empty
	ErrNoElement = errors.New("no element")

	// ErrTooManyElements is returned when an operation expects exactly one element but the slice has more
	ErrTooManyElements = errors.New("too many elements")
)

Functions

func And added in v0.5.0

func And[T any](filters ...func(T) bool) func(T) bool

And creates a filter function that combines multiple filters with logical AND. The returned filter returns true only if all the provided filters return true for a given value.

Example:

isEven := func(n int) bool { return n%2 == 0 }
isPositive := func(n int) bool { return n > 0 }
isEvenAndPositive := filter.And(isEven, isPositive)
// isEvenAndPositive(4) returns true
// isEvenAndPositive(-2) returns false

func Equals

func Equals[T comparable](v T) func(T) bool

Equals creates a filter function that checks if a value equals the provided value. This is a basic building block for creating more complex filters.

Example:

isThree := filter.Equals(3)
// isThree(3) returns true
// isThree(4) returns false

func FilterMap

func FilterMap[K comparable, V any](m map[K]V, filter func(V) bool) map[K]V

FilterMap filters a map using a single filter function. A key-value pair is included in the result only if the filter returns true for the value.

Parameters:

  • m: The input map to filter
  • filter: A function that takes a value and returns a boolean

Returns:

  • A new map containing only the key-value pairs where the value passed the filter

Example:

users := map[string]int{
    "alice": 25,
    "bob":   30,
    "carol": 22,
}
isOver25 := func(age int) bool { return age > 25 }
result := filter.FilterMap(users, isOver25)
// result = map[bob:30]

func FilterMapAnd

func FilterMapAnd[K comparable, V any](m map[K]V, filters ...func(V) bool) map[K]V

FilterMapAnd filters a map using multiple filter functions combined with logical AND. A key-value pair is included in the result only if all filters return true for the value.

Parameters:

  • m: The input map to filter
  • filters: A variadic list of filter functions

Returns:

  • A new map containing only the key-value pairs where the value passed all filters

Example:

users := map[string]User{
    "alice": {Age: 25, Role: "Admin"},
    "bob":   {Age: 30, Role: "User"},
    "carol": {Age: 22, Role: "Admin"},
}
isAdmin := func(u User) bool { return u.Role == "Admin" }
isOver25 := func(u User) bool { return u.Age > 25 }
result := filter.FilterMapAnd(users, isAdmin, isOver25)
// result contains only "alice"

func FilterMapNotAnd

func FilterMapNotAnd[K comparable, V any](m map[K]V, filters ...func(V) bool) map[K]V

FilterMapNotAnd filters a map using multiple filter functions combined with logical NOT AND. A key-value pair is included in the result if any of the filters return false for the value.

Parameters:

  • m: The input map to filter
  • filters: A variadic list of filter functions

Returns:

  • A new map containing the key-value pairs where the value failed at least one filter

Example:

users := map[string]User{
    "alice": {Age: 25, Role: "Admin"},
    "bob":   {Age: 30, Role: "User"},
    "carol": {Age: 22, Role: "Admin"},
}
isAdmin := func(u User) bool { return u.Role == "Admin" }
isOver25 := func(u User) bool { return u.Age > 25 }
result := filter.FilterMapNotAnd(users, isAdmin, isOver25)
// result contains "bob" and "carol" (either not admin or not over 25)

func FilterMapNotOr

func FilterMapNotOr[K comparable, V any](m map[K]V, filters ...func(V) bool) map[K]V

FilterMapNotOr filters a map using multiple filter functions combined with logical NOT OR. A key-value pair is included in the result only if all filters return false for the value.

Parameters:

  • m: The input map to filter
  • filters: A variadic list of filter functions

Returns:

  • A new map containing only the key-value pairs where the value failed all filters

Example:

users := map[string]User{
    "alice": {Age: 25, Role: "Admin"},
    "bob":   {Age: 30, Role: "User"},
    "carol": {Age: 22, Role: "Admin"},
}
isAdmin := func(u User) bool { return u.Role == "Admin" }
isOver25 := func(u User) bool { return u.Age > 25 }
result := filter.FilterMapNotOr(users, isAdmin, isOver25)
// result contains only "bob" (not admin and not over 25)

func FilterMapOr

func FilterMapOr[K comparable, V any](m map[K]V, filters ...func(V) bool) map[K]V

FilterMapOr filters a map using multiple filter functions combined with logical OR. A key-value pair is included in the result if any of the filters return true for the value.

Parameters:

  • m: The input map to filter
  • filters: A variadic list of filter functions

Returns:

  • A new map containing the key-value pairs where the value passed at least one filter

Example:

users := map[string]User{
    "alice": {Age: 25, Role: "Admin"},
    "bob":   {Age: 30, Role: "User"},
    "carol": {Age: 22, Role: "Admin"},
}
isAdmin := func(u User) bool { return u.Role == "Admin" }
isOver25 := func(u User) bool { return u.Age > 25 }
result := filter.FilterMapOr(users, isAdmin, isOver25)
// result contains "alice", "bob", and "carol"

func FilterSlice

func FilterSlice[T any](l []T, filter func(T) bool) []T

FilterSlice filters a slice using a single filter function. An element is included in the result only if the filter returns true for it.

Parameters:

  • l: The input slice to filter
  • filter: A function that takes an element and returns a boolean

Returns:

  • A new slice containing only the elements that passed the filter

Example:

numbers := []int{1, 2, 3, 4, 5}
isEven := func(n int) bool { return n%2 == 0 }
result := filter.FilterSlice(numbers, isEven)
// result = [2, 4]

func FilterSliceAnd

func FilterSliceAnd[T any](l []T, filters ...func(T) bool) []T

FilterSliceAnd filters a slice using multiple filter functions combined with logical AND. An element is included in the result only if all filters return true for it.

Parameters:

  • l: The input slice to filter
  • filters: A variadic list of filter functions

Returns:

  • A new slice containing only the elements that passed all filters

Example:

numbers := []int{1, 2, 3, 4, 5}
isEven := func(n int) bool { return n%2 == 0 }
isGreaterThanThree := func(n int) bool { return n > 3 }
result := filter.FilterSliceAnd(numbers, isEven, isGreaterThanThree)
// result = [4]

func FilterSliceNotAnd

func FilterSliceNotAnd[T any](l []T, filters ...func(T) bool) []T

FilterSliceNotAnd filters a slice using multiple filter functions combined with logical NOT AND. An element is included in the result if any of the filters return false for it.

Parameters:

  • l: The input slice to filter
  • filters: A variadic list of filter functions

Returns:

  • A new slice containing the elements for which at least one filter returned false

func FilterSliceNotOr

func FilterSliceNotOr[T any](l []T, filters ...func(T) bool) []T

FilterSliceNotOr filters a slice using multiple filter functions combined with logical NOT OR. An element is included in the result only if all filters return false for it.

Parameters:

  • l: The input slice to filter
  • filters: A variadic list of filter functions

Returns:

  • A new slice containing only the elements for which all filters returned false

func FilterSliceOr

func FilterSliceOr[T any](l []T, filters ...func(T) bool) []T

FilterSliceOr filters a slice using multiple filter functions combined with logical OR. An element is included in the result if any of the filters return true for it.

Parameters:

  • l: The input slice to filter
  • filters: A variadic list of filter functions

Returns:

  • A new slice containing the elements that passed at least one filter

Example:

numbers := []int{1, 2, 3, 4, 5}
isEven := func(n int) bool { return n%2 == 0 }
isLessThanTwo := func(n int) bool { return n < 2 }
result := filter.FilterSliceOr(numbers, isEven, isLessThanTwo)
// result = [1, 2, 4]

func NotAnd added in v0.5.0

func NotAnd[T any](filters ...func(T) bool) func(T) bool

NotAnd creates a filter function that combines multiple filters with logical NOT AND. The returned filter returns true only if at least one of the provided filters returns false for a given value.

Example:

isEven := func(n int) bool { return n%2 == 0 }
isPositive := func(n int) bool { return n > 0 }
isNotEvenOrNotPositive := filter.NotAnd(isEven, isPositive)
// isNotEvenOrNotPositive(4) returns false
// isNotEvenOrNotPositive(-2) returns true
// isNotEvenOrNotPositive(3) returns true

func NotOr added in v0.5.0

func NotOr[T any](filters ...func(T) bool) func(T) bool

NotOr creates a filter function that combines multiple filters with logical NOT OR. The returned filter returns true only if all of the provided filters return false for a given value.

Example:

isEven := func(n int) bool { return n%2 == 0 }
isNegative := func(n int) bool { return n < 0 }
isNotEvenAndNotNegative := filter.NotOr(isEven, isNegative)
// isNotEvenAndNotNegative(4) returns false
// isNotEvenAndNotNegative(-3) returns false
// isNotEvenAndNotNegative(3) returns true

func OneOnly

func OneOnly[T any](l []T) (*T, error)

OneOnly returns the only element in a slice, or an error if the slice doesn't contain exactly one element.

Parameters:

  • l: The input slice

Returns:

  • A pointer to the only element in the slice, or nil if an error occurred
  • An error: ErrNoElement if the slice is empty, ErrTooManyElements if it has more than one element

Example:

numbers := []int{42}
result, err := filter.OneOnly(numbers)
// result points to 42, err is nil

func Or added in v0.5.0

func Or[T any](filters ...func(T) bool) func(T) bool

Or creates a filter function that combines multiple filters with logical OR. The returned filter returns true if any of the provided filters return true for a given value.

Example:

isEven := func(n int) bool { return n%2 == 0 }
isNegative := func(n int) bool { return n < 0 }
isEvenOrNegative := filter.Or(isEven, isNegative)
// isEvenOrNegative(4) returns true
// isEvenOrNegative(-3) returns true
// isEvenOrNegative(3) returns false

func SliceSelectFirst

func SliceSelectFirst[T any](l []T) *T

SliceSelectFirst returns a pointer to the first element in a slice. This is useful when you need to access the first element without modifying the original slice.

Parameters:

  • l: The input slice

Returns:

  • A pointer to the first element, or nil if the slice is empty

Example:

items := []string{"apple", "banana", "cherry"}
first := filter.SliceSelectFirst(items)
// *first = "apple"

func SliceSelectLast

func SliceSelectLast[T any](l []T) *T

SliceSelectLast returns a pointer to the last element in a slice. This is useful when you need to access the last element without modifying the original slice.

Parameters:

  • l: The input slice

Returns:

  • A pointer to the last element, or nil if the slice is empty

Example:

items := []string{"apple", "banana", "cherry"}
last := filter.SliceSelectLast(items)
// *last = "cherry"

func SliceSelectRandom

func SliceSelectRandom[T any](l []T) *T

SliceSelectRandom returns a pointer to a random element in a slice. This function uses the default random number generator.

Note: This function is not cryptographically secure and should not be used for security-sensitive applications.

Parameters:

  • l: The input slice

Returns:

  • A pointer to a randomly selected element, or nil if the slice is empty

Example:

items := []string{"apple", "banana", "cherry"}
random := filter.SliceSelectRandom(items)
// *random = one of "apple", "banana", or "cherry"

func SliceSelectRandomWithGenerator

func SliceSelectRandomWithGenerator[T any](l []T, generator func(int) int) *T

SliceSelectRandomWithGenerator returns a pointer to a random element in a slice using a custom random number generator. This allows for deterministic random selection, which can be useful for testing.

Parameters:

  • l: The input slice
  • generator: A function that takes the length of the slice and returns a random index

Returns:

  • A pointer to a randomly selected element, or nil if the slice is empty or if generator is nil

Example:

items := []string{"apple", "banana", "cherry"}
// Always select the first element for testing
alwaysFirst := func(n int) int { return 0 }
result := filter.SliceSelectRandomWithGenerator(items, alwaysFirst)
// *result = "apple"

func SliceToAndFilter

func SliceToAndFilter[T any, U any](list []T, filterFunc func(T) func(U) bool) func(U) bool

SliceToAndFilter converts a slice of values into a single filter function using logical AND. The returned filter function returns true only if all of the individual filters (created from the slice elements) return true.

Parameters:

  • list: A slice of values to convert into filters
  • filterFunc: A function that converts each value in the list to a filter function

Returns:

  • A filter function that combines all the individual filters with logical AND

Example:

requiredTags := []string{"important", "urgent"}
hasAllRequiredTags := filter.SliceToAndFilter(requiredTags, func(tag string) func(task Task) bool {
    return func(task Task) bool { return task.HasTag(tag) }
})
// hasAllRequiredTags returns true only for tasks that have both "important" and "urgent" tags

func SliceToOrFilter

func SliceToOrFilter[T any, U any](list []T, filterFunc func(T) func(U) bool) func(U) bool

SliceToOrFilter converts a slice of values into a single filter function using logical OR. The returned filter function returns true if any of the individual filters (created from the slice elements) return true.

Parameters:

  • list: A slice of values to convert into filters
  • filterFunc: A function that converts each value in the list to a filter function

Returns:

  • A filter function that combines all the individual filters with logical OR

Example:

allowedIDs := []int{1, 3, 5}
hasAllowedID := filter.SliceToOrFilter(allowedIDs, func(id int) func(user User) bool {
    return func(user User) bool { return user.ID == id }
})
// hasAllowedID returns true for users with ID 1, 3, or 5

Types

This section is empty.

Jump to

Keyboard shortcuts

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