giter

package
v0.0.0-...-1e3dbca Latest Latest
Warning

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

Go to latest
Published: Aug 23, 2025 License: MIT Imports: 4 Imported by: 0

README

GITER - Go 1.23 Iterator LINQ

A LINQ-style operation library based on the newly introduced iter.Seq[T] in Go 1.23.

Requirements

  • Go 1.23 or higher

Features

Basic Operations
  • Where(predicate) — Filter elements
  • Select(selector) — Projection transformation
  • SelectMany(selector) — Flattening projection
  • Take(count) / TakeWhile(predicate) — Take first N/elements satisfying condition
  • Skip(count) / SkipWhile(predicate) — Skip first N/elements satisfying condition
  • Concat() — Concatenate sequences
  • Chunk(size) — Split into chunks
  • Append() / Prepend() — Append/Prepend elements
  • DefaultIfEmpty() — Provide default if sequence is empty
  • Aggregate() — Aggregate values
  • Count() / CountWhere(predicate) — Count elements
  • Any(predicate) / All(predicate) — Existence check
  • First() / FirstOrDefault() — Get first element
  • FirstWhere() / FirstWhereOrDefault() — Get first matching element
  • Last() / LastOrDefault() — Get last element
  • LastWhere() / LastWhereOrDefault() — Get last matching element
  • Single() / SingleOrDefault() — Get unique element
  • ElementAt() / ElementAtOrDefault() — Get element at index
  • Contains(value) — Contains check
  • SequenceEqual() — Sequence equality
Math Operations (math.go)
  • Min() / Max() — Minimum/Maximum values
  • MinBy(selector) / MaxBy(selector) — Minimum/Maximum by condition
  • Sum() / Average() — Sum/Average
Set Operations
  • Distinct() / DistinctBy(keySelector) — Remove duplicates
  • Union() / Intersect() / Except() — Set operations
Grouping and Sorting
  • GroupBy(keySelector) — Group by key (copies all items)
  • GroupByWithValue(keySelector, valueSelector) — Group and transform values
  • OrderBy(keySelector, less) / OrderByDescending() / ThenBy() — Sorting (see order.go)
Joining and Generation
  • Zip(other, resultSelector) — Zip operation
  • Range(start, count) — Generate number sequence
  • Repeat(value, count) — Repeat value sequence
  • Empty() — Empty sequence
Type & Utility
  • OfType[T, R]() — Filter by type (using type assertion)
  • Cast[T, R]() — Cast elements to another type
  • ToSlice() — Convert to slice
  • TryEach() — Safe iteration (error handling)
  • ForEach() — Simple iteration

Note: Reverse() is commented out due to performance concerns (see code for details).

Usage Examples

package main

import (
    "fmt"
    "slices"
    "github.com/szmcdull/glinq/giter"
)

func main() {
    numbers := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
    
    // Chain operations: filter even numbers, square them, take first 3
    result := giter.Take(
        giter.Select(
            giter.Where(slices.Values(numbers), func(x int) bool { return x%2 == 0 }),
            func(x int) int { return x * x },
        ),
        3,
    )
    
    fmt.Println(giter.ToSlice(result)) // [4, 16, 36]
    
    // Grouping example
    words := []string{"apple", "apricot", "banana", "cherry"}
    groups := giter.GroupBy(slices.Values(words), func(s string) byte { return s[0] })
    
    for group := range groups {
        fmt.Printf("%c: %v\n", group.Key, giter.ToSlice(group.Values))
    }
    // a: [apple apricot]
    // b: [banana]  
    // c: [cherry]
}

Differences from .NET LINQ

  • Reverse() is not implemented due to performance concerns.
  • Sorting (OrderBy, OrderByDescending, ThenBy) is implemented in order.go and may differ in usage.
  • Some methods (e.g., GroupBy) require full traversal and buffer all input.

Notes

  1. Most operations are lazily evaluated (streaming), but some (like GroupBy, OrderBy, etc.) require full traversal and buffer all input.
  2. Use TryEach to safely handle iterators that may panic.
  3. Chunk operation uses iter.Pull for efficient chunking.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func Aggregate

func Aggregate[T any, R any](it iter.Seq[T], initial R, accumulator func(R, T) R) R

func All

func All[T any](it iter.Seq[T], predicate func(T) bool) bool

All checks if all elements in the sequence satisfy the predicate.

func Any

func Any[T any](it iter.Seq[T], predicate func(T) bool) bool

func Append

func Append[T any](it iter.Seq[T], value T) iter.Seq[T]

func Average

func Average[T constraints.Integer | constraints.Float](it iter.Seq[T]) T

func Cast

func Cast[T, R any](it iter.Seq[T]) iter.Seq[R]

Cast attempts to cast each element to the specified type

func Chunk

func Chunk[T any](source iter.Seq[T], chunkSize int) iter.Seq[iter.Seq[T]]

There is no way to chunk a push iter. A poor way is to create a goproc to redirect the iter to push to a chan, then read the chan chunk by chunk in current goproc. iter.Pull makes it better by introducing a new lightweight coroutine (a stack-less state machine without preemption etc.)

func Concat

func Concat[T any](its ...iter.Seq[T]) iter.Seq[T]

func Contains

func Contains[T comparable](it iter.Seq[T], value T) bool

Contains checks if the sequence contains the specified value

func Count

func Count[T any](it iter.Seq[T]) int

Count returns the number of elements

func CountWhere

func CountWhere[T any](it iter.Seq[T], predicate func(T) bool) int

CountWhere returns the number of elements that satisfy the predicate

func DefaultIfEmpty

func DefaultIfEmpty[T any](it iter.Seq[T], defaultValue T) iter.Seq[T]

DefaultIfEmpty returns the sequence or a sequence with a single default value if empty

func Distinct

func Distinct[T comparable](it iter.Seq[T]) iter.Seq[T]

func DistinctBy

func DistinctBy[T any, K comparable](it iter.Seq[T], keySelector func(T) K) iter.Seq[T]

DistinctBy returns distinct elements based on a key selector function

func ElementAt

func ElementAt[T any](it iter.Seq[T], index int) T

ElementAt returns the element at the specified index

func ElementAtOrDefault

func ElementAtOrDefault[T any](it iter.Seq[T], index int) T

ElementAtOrDefault returns the element at the specified index or zero value

func Empty

func Empty[T any]() iter.Seq[T]

Empty returns an empty sequence

func Except

func Except[T comparable](first, second iter.Seq[T]) iter.Seq[T]

Except returns the set difference of two sequences

func First

func First[T any](it iter.Seq[T]) T

First returns the first element or panics if empty

func FirstOrDefault

func FirstOrDefault[T any](it iter.Seq[T]) T

FirstOrDefault returns the first element or zero value if empty

func FirstWhere

func FirstWhere[T any](it iter.Seq[T], predicate func(T) bool) T

FirstWhere returns the first element that satisfies the predicate

func FirstWhereOrDefault

func FirstWhereOrDefault[T any](it iter.Seq[T], predicate func(T) bool) T

FirstWhereOrDefault returns the first element that satisfies the predicate or zero value

func ForEach

func ForEach[T any](it iter.Seq[T], yield func(T) bool)

func GroupBy

func GroupBy[T any, K comparable](it iter.Seq[T], keySelector func(T) K) iter.Seq[Grouping[K, T]]

GroupBy groups elements by a key selector. It has to COPY ALL items.

func GroupByWithValue

func GroupByWithValue[T any, K comparable, V any](it iter.Seq[T], keySelector func(T) K, valueSelector func(T) V) iter.Seq[Grouping[K, V]]

GroupByWithValue groups elements by a key selector and transforms values. It has to COPY ALL items.

func Intersect

func Intersect[T comparable](first, second iter.Seq[T]) iter.Seq[T]

Intersect returns the set intersection of two sequences

func Last

func Last[T any](it iter.Seq[T]) T

Last returns the last element or panics if empty

func LastOrDefault

func LastOrDefault[T any](it iter.Seq[T]) T

LastOrDefault returns the last element or zero value if empty

func LastWhere

func LastWhere[T any](it iter.Seq[T], predicate func(T) bool) T

LastWhere returns the last element that satisfies the predicate

func LastWhereOrDefault

func LastWhereOrDefault[T any](it iter.Seq[T], predicate func(T) bool) T

LastWhereOrDefault returns the last element that satisfies the predicate or zero value

func Max

func Max[T constraints.Ordered](it iter.Seq[T]) T

func MaxBy

func MaxBy[T any, V constraints.Ordered](it iter.Seq[T], selector func(T) V) T

func Min

func Min[T constraints.Ordered](it iter.Seq[T]) T

func MinBy

func MinBy[T any, V constraints.Ordered](it iter.Seq[T], selector func(T) V) T

func OfType

func OfType[T, R any](it iter.Seq[T]) iter.Seq[R]

OfType filters elements to those of a specific type (using type assertion) This is a simplified version since Go doesn't have runtime type information like .NET

func Order

func Order[T any](it iter.Seq[T], spec OrderSpec[T]) iter.Seq[T]

Order sorts the sequence using the specified multi-level ordering criteria. The OrderSpec parameter should be built using By() and Then() functions.

This function materializes the entire sequence into a slice, sorts it using Go's stable sort, and then yields the sorted elements.

Example:

sorted := Order(seq, By(ageSelector, intLess).Then(nameSelector, stringLess))

Multi-level example:

sorted := Order(seq,
  Then(
    ThenDescending(
      By(gradeSelector, intLess),           // Primary: grade ascending
      scoreSelector, intLess),              // Secondary: score descending
    nameSelector, stringLess))              // Tertiary: name ascending

func OrderBy

func OrderBy[T any](it iter.Seq[T], less func(a, b T) bool) iter.Seq[T]

OrderBy sorts the sequence using a single less function, similar to sort.SliceStable. Example:

OrderBy(seq, func(a, b Person) bool {
    if a.Age != b.Age { return a.Age < b.Age }
    return a.Name < b.Name
})

func Prepend

func Prepend[T any](it iter.Seq[T], value T) iter.Seq[T]

Prepend adds an element to the beginning of the sequence

func Range

func Range(start, count int) iter.Seq[int]

Range generates a sequence of integers

func Repeat

func Repeat[T any](value T, count int) iter.Seq[T]

Repeat generates a sequence with a repeated value

func Select

func Select[T, R any](it iter.Seq[T], selector func(T) R) iter.Seq[R]

Select projects each element to a new form

func SelectMany

func SelectMany[T, R any](it iter.Seq[T], selector func(T) iter.Seq[R]) iter.Seq[R]

SelectMany flattens sequences

func SequenceEqual

func SequenceEqual[T comparable](first, second iter.Seq[T]) bool

SequenceEqual determines whether two sequences are equal

func Single

func Single[T any](it iter.Seq[T]) T

Single returns the only element or panics

func SingleOrDefault

func SingleOrDefault[T any](it iter.Seq[T]) T

SingleOrDefault returns the only element or zero value

func Skip

func Skip[T any](it iter.Seq[T], count int) iter.Seq[T]

Skip skips the first n elements

func SkipWhile

func SkipWhile[T any](it iter.Seq[T], predicate func(T) bool) iter.Seq[T]

SkipWhile skips elements while the predicate is true

func Sum

func Sum[T constraints.Integer | constraints.Float](it iter.Seq[T]) T

func Take

func Take[T any](it iter.Seq[T], count int) iter.Seq[T]

Take returns the first n elements

func TakeWhile

func TakeWhile[T any](it iter.Seq[T], predicate func(T) bool) iter.Seq[T]

TakeWhile returns elements while the predicate is true

func ToSlice

func ToSlice[T any](it iter.Seq[T]) []T

ToSlice converts the iterator to a slice

func TryEach

func TryEach[T any](it iter.Seq[T], yield func(T) bool) (err error)

func Union

func Union[T comparable](first, second iter.Seq[T]) iter.Seq[T]

Union returns the set union of two sequences (removes duplicates)

func Where

func Where[T any](it iter.Seq[T], predicate func(T) bool) iter.Seq[T]

Where filters elements based on a predicate

func Zip

func Zip[T, U, R any](first iter.Seq[T], second iter.Seq[U], resultSelector func(T, U) R) iter.Seq[R]

Zip combines two sequences into one

Types

type Grouping

type Grouping[K comparable, V any] struct {
	Key    K
	Values iter.Seq[V]
}

GroupBy groups elements by a key selector

type OrderSpec

type OrderSpec[T any] struct {
	// contains filtered or unexported fields
}

OrderSpec represents a multi-level ordering specification that can be built using a fluent API for complex sorting scenarios.

Example usage:

Order(seq, By(keyFunc, lessFunc).Then(keyFunc2, lessFunc2).ThenDescending(keyFunc3, lessFunc3))

Or step by step:

spec := By(keyFunc, lessFunc)
spec = Then(spec, keyFunc2, lessFunc2)
spec = ThenDescending(spec, keyFunc3, lessFunc3)
result := Order(seq, spec)

func By

func By[T any, K any](keySelector func(T) K, less func(K, K) bool) OrderSpec[T]

By creates a new OrderSpec with the first ordering criteria in ascending order. This is the starting point for building multi-level sort specifications.

Example:

spec := By(func(p Person) int { return p.Age }, func(a, b int) bool { return a < b })

func ByDescending

func ByDescending[T any, K any](keySelector func(T) K, less func(K, K) bool) OrderSpec[T]

ByDescending creates a new OrderSpec with the first ordering criteria in descending order.

Example:

spec := ByDescending(func(p Person) int { return p.Age }, func(a, b int) bool { return a < b })

func Then

func Then[T any, K any](spec OrderSpec[T], keySelector func(T) K, less func(K, K) bool) OrderSpec[T]

Then adds a secondary ordering criteria in ascending order. This allows chaining multiple sort criteria where subsequent criteria are used to break ties from previous criteria.

Example:

spec = Then(spec, func(p Person) string { return p.Name }, func(a, b string) bool { return a < b })

func ThenDescending

func ThenDescending[T any, K any](spec OrderSpec[T], keySelector func(T) K, less func(K, K) bool) OrderSpec[T]

ThenDescending adds a secondary ordering criteria in descending order.

Example:

spec = ThenDescending(spec, func(p Person) int { return p.Score }, func(a, b int) bool { return a < b })

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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