go2linq

package module
v4.0.0-beta.6 Latest Latest
Warning

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

Go to latest
Published: Nov 18, 2024 License: MIT Imports: 14 Imported by: 0

README

go2linq

Go Reference

go2linq v4 is Go implementation of .NET's LINQ to Objects. (See also: Language Integrated Query, LINQ, Enumerable Class.)

go2linq v4 is based on iter.Seq, so it requires setting GOEXPERIMENT=rangefunc when executing go commands.


Installation

go get github.com/solsw/go2linq/v4

Examples

Examples of go2linq usage are in the Example... functions in test files (see Examples).

Quick and easy example:
package main

import (
	"fmt"

	"github.com/solsw/go2linq/v4"
)

func main() {
	filter, _ := go2linq.Where(
		go2linq.VarAll(1, 2, 3, 4, 5, 6, 7, 8),
		func(i int) bool { return i > 6 || i%2 == 0 },
	)
	squares, _ := go2linq.Select(
		filter,
		func(i int) string { return fmt.Sprintf("%d: %d", i, i*i) },
	)
	for square := range squares {
		fmt.Println(square)
	}
}

The previous code outputs the following:

2: 4
4: 16
6: 36
7: 49
8: 64

Documentation

Overview

Package go2linq implements (v4 based on iter.Seq) .NET's LINQ to Objects.

See also:

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	ErrDuplicateKeys    = errors.New("duplicate keys")
	ErrEmptySource      = errors.New("empty source")
	ErrIndexOutOfRange  = errors.New("index out of range")
	ErrMultipleElements = errors.New("multiple elements")
	ErrMultipleMatch    = errors.New("multiple match")
	ErrNegativeCount    = errors.New("negative count")
	ErrNilAccumulator   = errors.New("nil accumulator")
	ErrNilAction        = errors.New("nil action")
	ErrNilCompare       = errors.New("nil compare")
	ErrNilEqual         = errors.New("nil equal")
	ErrNilLess          = errors.New("nil less")
	ErrNilPredicate     = errors.New("nil predicate")
	ErrNilSelector      = errors.New("nil selector")
	ErrNilSource        = errors.New("nil source")
	ErrNoMatch          = errors.New("no match")
	ErrSizeOutOfRange   = errors.New("size out of range")
)

Functions

func Aggregate

func Aggregate[Source any](source iter.Seq[Source], accumulator func(Source, Source) Source) (Source, error)

Aggregate applies an accumulator function over a sequence.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.aggregate

sentence := "the quick brown fox jumps over the lazy dog"
// Split the string into individual words.
words := strings.Fields(sentence)
// Prepend each word to the beginning of the new sentence to reverse the word order.
reversed, _ := Aggregate(
	slices.Values(words),
	func(workingSentence, next string) string { return next + " " + workingSentence },
)
fmt.Println(reversed)
Output:

dog lazy the over jumps fox brown quick the

func AggregateBy

func AggregateBy[Source, Key, Accumulate any](source iter.Seq[Source], keySelector func(Source) Key,
	seed Accumulate, accumulator func(Accumulate, Source) Accumulate) (iter.Seq[generichelper.Tuple2[Key, Accumulate]], error)

AggregateBy applies an accumulator function over a sequence, grouping results by key. 'seed' is the initial accumulator value for each key. Key values are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

func AggregateByEq

func AggregateByEq[Source, Key, Accumulate any](source iter.Seq[Source],
	keySelector func(Source) Key, seed Accumulate, accumulator func(Accumulate, Source) Accumulate,
	keyEqual func(Key, Key) bool) (iter.Seq[generichelper.Tuple2[Key, Accumulate]], error)

AggregateByEq applies an accumulator function over a sequence, grouping results by key. 'seed' is the initial accumulator value for each key. Key values are compared using 'keyEqual'. 'source' is enumerated immediately.

func AggregateBySel

func AggregateBySel[Source, Key, Accumulate any](source iter.Seq[Source], keySelector func(Source) Key,
	seedSelector func(Key) Accumulate, accumulator func(Accumulate, Source) Accumulate) (iter.Seq[generichelper.Tuple2[Key, Accumulate]], error)

AggregateBySel applies an accumulator function over a sequence, grouping results by key. 'seedSelector' is a factory for the initial accumulator value for each particular key. Key values are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

func AggregateBySelEq

func AggregateBySelEq[Source, Key, Accumulate any](source iter.Seq[Source], keySelector func(Source) Key,
	seedSelector func(Key) Accumulate, accumulator func(Accumulate, Source) Accumulate,
	keyEqual func(Key, Key) bool) (iter.Seq[generichelper.Tuple2[Key, Accumulate]], error)

AggregateBySelEq applies an accumulator function over a sequence, grouping results by key. 'seedSelector' is a factory for the initial accumulator value for each particular key. Key values are compared using 'keyEqual'. 'source' is enumerated immediately.

func AggregateSeed

func AggregateSeed[Source, Accumulate any](source iter.Seq[Source],
	seed Accumulate, accumulator func(Accumulate, Source) Accumulate) (Accumulate, error)

AggregateSeed applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.aggregate

ints := []int{4, 8, 8, 3, 9, 0, 7, 8, 2}
// Count the even numbers in the array, using a seed value of 0.
numEven, _ := AggregateSeed(
	slices.Values(ints),
	0,
	func(total, next int) int {
		if next%2 == 0 {
			return total + 1
		}
		return total
	},
)
fmt.Printf("The number of even integers is: %d\n", numEven)
Output:

The number of even integers is: 6

func AggregateSeedSel

func AggregateSeedSel[Source, Accumulate, Result any](source iter.Seq[Source], seed Accumulate,
	accumulator func(Accumulate, Source) Accumulate, resultSelector func(Accumulate) Result) (Result, error)

AggregateSeedSel applies an accumulator function over a sequence. The specified seed value is used as the initial accumulator value, and the specified function is used to select the result value.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.aggregate

fruits := []string{"apple", "mango", "orange", "passionfruit", "grape"}
// Determine whether any string in the array is longer than "banana".
longestName, _ := AggregateSeedSel(
	slices.Values(fruits),
	"banana",
	func(longest, next string) string {
		if len(next) > len(longest) {
			return next
		}
		return longest
	},
	// Return the final result as an upper case string.
	func(fruit string) string { return strings.ToUpper(fruit) },
)
fmt.Printf("The fruit with the longest name is %s.\n", longestName)
Output:

The fruit with the longest name is PASSIONFRUIT.

func All

func All[Source any](source iter.Seq[Source], predicate func(Source) bool) (bool, error)

All determines whether all elements of a sequence satisfy a condition.

Example (Ex1)

AllEx example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.all#examples

pets := []Pet{
	{Name: "Barley", Age: 10},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 6},
}
// Determine whether all Pet names in the array start with 'B'.
allStartWithB, _ := All(
	slices.Values(pets),
	func(pet Pet) bool { return strings.HasPrefix(pet.Name, "B") },
)
var what string
if allStartWithB {
	what = "All"
} else {
	what = "Not all"
}
fmt.Printf("%s pet names start with 'B'.\n", what)
Output:

Not all pet names start with 'B'.
Example (Ex2)

AllEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.all#examples

people := []Person{
	{
		LastName: "Haas",
		Pets: []Pet{
			{Name: "Barley", Age: 10},
			{Name: "Boots", Age: 14},
			{Name: "Whiskers", Age: 6},
		},
	},
	{
		LastName: "Fakhouri",
		Pets: []Pet{
			{Name: "Snowball", Age: 1},
		},
	},
	{
		LastName: "Antebi",
		Pets: []Pet{
			{Name: "Belle", Age: 8},
		},
	},
	{
		LastName: "Philips",
		Pets: []Pet{
			{Name: "Sweetie", Age: 2},
			{Name: "Rover", Age: 13},
		},
	},
}
// Determine which people have Pets that are all older than 5.
where, _ := Where(
	slices.Values(people),
	func(person Person) bool {
		return errorhelper.Must(All(
			slices.Values(person.Pets),
			func(pet Pet) bool { return pet.Age > 5 },
		))
	},
)
names, _ := Select(
	where,
	func(person Person) string { return person.LastName },
)
for name := range names {
	fmt.Println(name)
}
Output:

Haas
Antebi
Example (Ex3)

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#query-expression-syntax-examples https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#all

markets := []Market{
	{Name: "Emily's", Items: []string{"kiwi", "cheery", "banana"}},
	{Name: "Kim's", Items: []string{"melon", "mango", "olive"}},
	{Name: "Adam's", Items: []string{"kiwi", "apple", "orange"}},
}
where, _ := Where(
	slices.Values(markets),
	func(m Market) bool {
		return errorhelper.Must(All(
			slices.Values(m.Items),
			func(item string) bool { return len(item) == 5 },
		))
	},
)
names, _ := Select(where, func(m Market) string { return m.Name })
for name := range names {
	fmt.Printf("%s market\n", name)
}
Output:

Kim's market

func Any

func Any[Source any](source iter.Seq[Source]) (bool, error)

Any determines whether a sequence contains any elements.

Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.any

numbers := []int{1, 2}
hasElements, _ := Any(VarToSeq(numbers...))
var what string
if hasElements {
	what = "is not"
} else {
	what = "is"
}
fmt.Printf("The list %s empty.\n", what)
Output:

The list is not empty.
Example (Ex2)

AnyEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.any

people := []Person{
	{
		LastName: "Haas",
		Pets: []Pet{
			{Name: "Barley", Age: 10},
			{Name: "Boots", Age: 14},
			{Name: "Whiskers", Age: 6},
		},
	},
	{
		LastName: "Fakhouri",
		Pets: []Pet{
			{Name: "Snowball", Age: 1},
		},
	},
	{
		LastName: "Antebi",
		Pets:     []Pet{},
	},
	{
		LastName: "Philips",
		Pets: []Pet{
			{Name: "Sweetie", Age: 2},
			{Name: "Rover", Age: 13},
		},
	},
}
// Determine which people have a non-empty Pet array.
where, _ := Where(
	slices.Values(people),
	func(person Person) bool { return errorhelper.Must(Any(slices.Values(person.Pets))) },
)
names, _ := Select(
	where,
	func(person Person) string { return person.LastName },
)
for name := range names {
	fmt.Println(name)
}
Output:

Haas
Fakhouri
Philips

func AnyPred

func AnyPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (bool, error)

AnyPred determines whether any element of a sequence satisfies a condition.

Example (Ex1)

AnyEx3 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.any

pets := []Pet{
	{Name: "Barley", Age: 8, Vaccinated: true},
	{Name: "Boots", Age: 4, Vaccinated: false},
	{Name: "Whiskers", Age: 1, Vaccinated: false},
}
// Determine whether any pets over Age 1 are also unvaccinated.
unvaccinated, _ := AnyPred(
	slices.Values(pets),
	func(pet Pet) bool { return pet.Age > 1 && pet.Vaccinated == false },
)
var what string
if unvaccinated {
	what = "are"
} else {
	what = "are not any"
}
fmt.Printf("There %s unvaccinated animals over age one.\n", what)
Output:

There are unvaccinated animals over age one.
Example (Ex2)

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#query-expression-syntax-examples https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#any

markets := []Market{
	{Name: "Emily's", Items: []string{"kiwi", "cheery", "banana"}},
	{Name: "Kim's", Items: []string{"melon", "mango", "olive"}},
	{Name: "Adam's", Items: []string{"kiwi", "apple", "orange"}},
}
where, _ := Where(
	slices.Values(markets),
	func(m Market) bool {
		return errorhelper.Must(AnyPred(
			slices.Values(m.Items),
			func(item string) bool { return strings.HasPrefix(item, "o") },
		))
	},
)
names, _ := Select(where, func(m Market) string { return m.Name })
for name := range names {
	fmt.Printf("%s market\n", name)
}
Output:

Kim's market
Adam's market

func Append

func Append[Source any](source iter.Seq[Source], element Source) (iter.Seq[Source], error)

Append appends a value to the end of the sequence.

func ApplyResultSelector

func ApplyResultSelector[Key, Element, Result any](lookup *Lookup[Key, Element],
	resultSelector func(Key, iter.Seq[Element]) Result) (iter.Seq[Result], error)

ApplyResultSelector applies a transform function to each key and its associated values and returns the results.

func Average

func Average[Source constraints.Integer | constraints.Float](source iter.Seq[Source]) (float64, error)

Average computes the average of a sequence of constraints.Integer or constraints.Float values.

Example (Ex1)

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.average

grades := []int{78, 92, 100, 37, 81}
average, _ := Average(slices.Values(grades))
fmt.Printf("The average grade is %g.\n", average)
Output:

The average grade is 77.6.
Example (Ex2)

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.average

numbers := []string{"10007", "37", "299846234235"}
average, _ := AverageSel(
	slices.Values(numbers),
	func(e string) int {
		r, _ := strconv.Atoi(e)
		return r
	},
)
fmt.Printf("The average is %.f.\n", average)
Output:

The average is 99948748093.

func AverageSel

func AverageSel[Source any, Result constraints.Integer | constraints.Float](source iter.Seq[Source],
	selector func(Source) Result) (float64, error)

AverageSel computes the average of a sequence of constraints.Integer or constraints.Float values that are obtained by invoking a transform function on each element of the input sequence.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.average

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
average, _ := AverageSel(
	slices.Values(fruits),
	func(e string) int { return len(e) },
)
fmt.Printf("The average string length is %g.\n", average)
Output:

The average string length is 6.5.

func Cast

func Cast[Source, Result any](source iter.Seq[Source]) (iter.Seq[Result], error)

Cast casts the elements of a sequence to a specified type.

func ChanAll

func ChanAll[E any](c <-chan E) iter.Seq[E]

ChanAll converts a channel to a sequence. If 'c' is nil, empty sequence is returned.

Example
seq1 := ChanAll[int](chn3())
seq2, _ := Select[int](seq1, func(i int) int { return 12 / i })
first1, _ := First[int](seq2)
fmt.Println(first1)
skip, _ := Skip[int](seq2, 2)
first2, _ := First[int](skip)
fmt.Println(first2)
Output:

3
12

func ChanAll2

func ChanAll2[E any](c <-chan E) iter.Seq2[int, E]

ChanAll2 converts a channel to a sequence2. If 'c' is nil, empty sequence2 is returned.

func Chunk

func Chunk[Source any](source iter.Seq[Source], size int) (iter.Seq[[]Source], error)

Chunk splits the elements of a sequence into chunks of size at most 'size'.

Example

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/partitioning-data#example

chunkNumber := 0
rng, _ := Range(0, 8)
chunk, _ := Chunk(rng, 3)
for ii := range chunk {
	chunkNumber++
	fmt.Printf("Chunk %d:%v\n", chunkNumber, ii)
}
Output:

Chunk 1:[0 1 2]
Chunk 2:[3 4 5]
Chunk 3:[6 7]

func Concat

func Concat[Source any](first, second iter.Seq[Source]) (iter.Seq[Source], error)

Concat concatenates two sequences.

Example

ConcatEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.concat#examples

cats := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
dogs := []Pet{
	{Name: "Bounder", Age: 3},
	{Name: "Snoopy", Age: 14},
	{Name: "Fido", Age: 9},
}
concat, _ := Concat(
	errorhelper.Must(Select(
		slices.Values(cats),
		func(cat Pet) string { return cat.Name },
	)),
	errorhelper.Must(Select(
		slices.Values(dogs),
		func(dog Pet) string { return dog.Name },
	)),
)
for name := range concat {
	fmt.Println(name)
}
Output:

Barley
Boots
Whiskers
Bounder
Snoopy
Fido

func Contains

func Contains[Source any](source iter.Seq[Source], value Source) (bool, error)

Contains determines whether a sequence contains a specified element using generichelper.DeepEqual.

Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.contains

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
fruit := "mango"
hasMango, _ := Contains(slices.Values(fruits), fruit)
var what string
if hasMango {
	what = "does"
} else {
	what = "does not"
}
fmt.Printf("The array %s contain '%s'.\n", what, fruit)
Output:

The array does contain 'mango'.
Example (Ex2)

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#query-expression-syntax-examples https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/quantifier-operations#contains

markets := []Market{
	{Name: "Emily's", Items: []string{"kiwi", "cheery", "banana"}},
	{Name: "Kim's", Items: []string{"melon", "mango", "olive"}},
	{Name: "Adam's", Items: []string{"kiwi", "apple", "orange"}},
}
where, _ := Where(
	slices.Values(markets),
	func(m Market) bool {
		return errorhelper.Must(Contains(slices.Values(m.Items), "kiwi"))
	},
)
names, _ := Select(where, func(m Market) string { return m.Name })
for name := range names {
	fmt.Printf("%s market\n", name)
}
Output:

Emily's market
Adam's market

func ContainsEq

func ContainsEq[Source any](source iter.Seq[Source], value Source, equal func(Source, Source) bool) (bool, error)

ContainsEq determines whether a sequence contains a specified element using a specified 'equal'.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.contains

fruits := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
	{Name: "lemon", Code: 12},
}
apple := Product{Name: "apple", Code: 9}
kiwi := Product{Name: "kiwi", Code: 8}
var equal = func(p1, p2 Product) bool {
	return p1.Code == p2.Code && p1.Name == p2.Name
}
hasApple, _ := ContainsEq(VarToSeq(fruits...), apple, equal)
hasKiwi, _ := ContainsEq(VarToSeq(fruits...), kiwi, equal)
fmt.Printf("Apple? %t\n", hasApple)
fmt.Printf("Kiwi? %t\n", hasKiwi)
Output:

Apple? true
Kiwi? false

func Count

func Count[Source any](source iter.Seq[Source]) (int, error)

Count returns the number of elements in a sequence.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.count

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
numberOfFruits, _ := Count(slices.Values(fruits))
fmt.Printf("There are %d fruits in the collection.\n", numberOfFruits)
Output:

There are 6 fruits in the collection.

func CountBy

func CountBy[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key) (iter.Seq[generichelper.Tuple2[Key, int]], error)

CountBy returns the count of elements in the source sequence grouped by key. Key values are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

func CountByEq

func CountByEq[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key,
	keyEqual func(Key, Key) bool) (iter.Seq[generichelper.Tuple2[Key, int]], error)

CountByEq returns the count of elements in the source sequence grouped by key. Key values are compared using 'keyEqual'. 'source' is enumerated immediately.

func CountPred

func CountPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (int, error)

CountPred returns a number that represents how many elements in a specified sequence satisfy a condition.

Example (Ex1)

CountEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.count

pets := []Pet{
	{Name: "Barley", Vaccinated: true},
	{Name: "Boots", Vaccinated: false},
	{Name: "Whiskers", Vaccinated: false},
}
numberUnvaccinated, _ := CountPred(
	slices.Values(pets),
	func(p Pet) bool { return p.Vaccinated == false },
)
fmt.Printf("There are %d unvaccinated animals.\n", numberUnvaccinated)
Output:

There are 2 unvaccinated animals.
Example (Ex2)

LongCountEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.longcount

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
const Age = 3
count, _ := CountPred(
	slices.Values(pets),
	func(pet Pet) bool { return pet.Age > Age },
)
fmt.Printf("There are %d animals over age %d.\n", count, Age)
Output:

There are 2 animals over age 3.

func DefaultIfEmpty

func DefaultIfEmpty[Source any](source iter.Seq[Source]) (iter.Seq[Source], error)

DefaultIfEmpty returns the elements of a specified sequence or the type parameter's zero value in a singleton collection if the sequence is empty.

Example (Ex1)

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.defaultifempty

numbers, _ := DefaultIfEmpty(slices.Values([]int{}))
for number := range numbers {
	fmt.Println(number)
}
Output:

0
Example (Ex2)

DefaultIfEmptyEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.defaultifempty

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
defaultIfEmpty, _ := DefaultIfEmpty(slices.Values(pets))
for pet := range defaultIfEmpty {
	fmt.Println(pet.Name)
}
Output:

Barley
Boots
Whiskers

func DefaultIfEmptyDef

func DefaultIfEmptyDef[Source any](source iter.Seq[Source], defaultValue Source) (iter.Seq[Source], error)

DefaultIfEmptyDef returns the elements of a specified sequence or a specified value in a singleton collection if the sequence is empty.

Example

DefaultIfEmptyEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.defaultifempty

defaultPet := Pet{Name: "Default Pet", Age: 0}
pets1 := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
defaultIfEmptyDef1, _ := DefaultIfEmptyDef(slices.Values(pets1), defaultPet)
for pet := range defaultIfEmptyDef1 {
	fmt.Printf("Name: %s\n", pet.Name)
}
pets2 := []Pet{}
defaultIfEmptyDef2, _ := DefaultIfEmptyDef(slices.Values(pets2), defaultPet)
for pet := range defaultIfEmptyDef2 {
	fmt.Printf("\nName: %s\n", pet.Name)
}
Output:

Name: Barley
Name: Boots
Name: Whiskers

Name: Default Pet

func Distinct

func Distinct[Source any](source iter.Seq[Source]) (iter.Seq[Source], error)

Distinct returns distinct elements from a sequence using generichelper.DeepEqual to compare values. Order of elements in the result corresponds to the order of elements in 'source'.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinct

ages := []int{21, 46, 46, 55, 17, 21, 55, 55}
distinct, _ := Distinct(slices.Values(ages))
fmt.Println("Distinct ages:")
for age := range distinct {
	fmt.Println(age)
}
Output:

Distinct ages:
21
46
55
17

func DistinctBy

func DistinctBy[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key) (iter.Seq[Source], error)

DistinctBy returns distinct elements from a sequence according to a specified key selector function and using generichelper.DeepEqual to compare keys.

func DistinctByCmp

func DistinctByCmp[Source, Key any](source iter.Seq[Source],
	keySelector func(Source) Key, compare func(Key, Key) int) (iter.Seq[Source], error)

DistinctByCmp returns distinct elements from a sequence according to a specified key selector function and using a specified 'compare' to compare keys. (See DistinctCmp.)

func DistinctByEq

func DistinctByEq[Source, Key any](source iter.Seq[Source],
	keySelector func(Source) Key, keyEqual func(Key, Key) bool) (iter.Seq[Source], error)

DistinctByEq returns distinct elements from a sequence according to a specified key selector function and using a specified 'keyEqual' to compare keys.

func DistinctCmp

func DistinctCmp[Source any](source iter.Seq[Source], compare func(Source, Source) int) (iter.Seq[Source], error)

DistinctCmp returns distinct elements from a sequence using a specified 'compare' to compare values. Order of elements in the result corresponds to the order of elements in 'source'.

Sorted slice of already seen elements is internally built. Sorted slice allows to use binary search to determine whether the element was seen or not. This may give performance gain when processing large sequences (though this is a subject for benchmarking, see [BenchmarkDistinctEqMust] and [BenchmarkDistinctCmpMust]).

func DistinctEq

func DistinctEq[Source any](source iter.Seq[Source], equal func(Source, Source) bool) (iter.Seq[Source], error)

DistinctEq returns distinct elements from a sequence using a specified 'equal' to compare values. Order of elements in the result corresponds to the order of elements in 'source'.

Example

last two examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.distinct

products := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
	{Name: "Apple", Code: 9},
	{Name: "lemon", Code: 12},
}
//Exclude duplicates.
distinctEq, _ := DistinctEq(slices.Values(products), func(p1, p2 Product) bool {
	return p1.Code == p2.Code && strings.EqualFold(p1.Name, p2.Name)
})
for product := range distinctEq {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

apple 9
orange 4
lemon 12

func ElementAt

func ElementAt[Source any](source iter.Seq[Source], index int) (Source, error)

ElementAt returns the element at a specified index in a sequence.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.elementat

names := []string{"Hartono, Tommy", "Adams, Terry", "Andersen, Henriette Thaulow", "Hedlund, Magnus", "Ito, Shu"}
r := rand.New(rand.NewSource(623))
name, _ := ElementAt(slices.Values(names), r.Intn(len(names)))
fmt.Printf("The name chosen at random is '%s'.\n", name)
Output:

The name chosen at random is 'Hedlund, Magnus'.

func ElementAtOrDefault

func ElementAtOrDefault[Source any](source iter.Seq[Source], index int) (Source, error)

ElementAtOrDefault returns the element at a specified index in a sequence or a zero value if the index is out of range.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.elementatordefault

names := []string{"Hartono, Tommy", "Adams, Terry", "Andersen, Henriette Thaulow", "Hedlund, Magnus", "Ito, Shu"}
index := 20
name, _ := ElementAtOrDefault(slices.Values(names), index)
var what string
if name == "" {
	what = "<no name at this index>"
} else {
	what = name
}
fmt.Printf("The name chosen at index %d is '%s'.\n", index, what)
Output:

The name chosen at index 20 is '<no name at this index>'.

func Empty

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

Empty returns an empty sequence that has a specified type argument.

func Empty2

func Empty2[K, V any]() iter.Seq2[K, V]

Empty2 returns an empty sequence2 that has a specified type arguments.

func Except

func Except[Source any](first, second iter.Seq[Source]) (iter.Seq[Source], error)

Except produces the set difference of two sequences using generichelper.DeepEqual to compare values. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.except

numbers1 := VarToSeq(2.0, 2.0, 2.1, 2.2, 2.3, 2.3, 2.4, 2.5)
numbers2 := VarToSeq(2.2)
except, _ := Except(numbers1, numbers2)
for number := range except {
	fmt.Println(number)
}
Output:

2
2.1
2.3
2.4
2.5

func ExceptBy

func ExceptBy[Source, Key any](first iter.Seq[Source], second iter.Seq[Key], keySelector func(Source) Key) (iter.Seq[Source], error)

ExceptBy produces the set difference of two sequences according to a specified key selector function and using generichelper.DeepEqual as key equaler. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func ExceptByCmp

func ExceptByCmp[Source, Key any](first iter.Seq[Source], second iter.Seq[Key],
	keySelector func(Source) Key, compare func(Key, Key) int) (iter.Seq[Source], error)

ExceptByCmp produces the set difference of two sequences according to a specified key selector function and using a specified 'compare' to compare keys. (See DistinctCmp.) 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func ExceptByEq

func ExceptByEq[Source, Key any](first iter.Seq[Source], second iter.Seq[Key],
	keySelector func(Source) Key, keyEqual func(Key, Key) bool) (iter.Seq[Source], error)

ExceptByEq produces the set difference of two sequences according to a specified key selector function and using a specified key equaler. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func ExceptCmp

func ExceptCmp[Source any](first, second iter.Seq[Source], compare func(Source, Source) int) (iter.Seq[Source], error)

ExceptCmp produces the set difference of two sequences using 'compare' to compare values. (See DistinctCmp.) 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func ExceptEq

func ExceptEq[Source any](first, second iter.Seq[Source], equal func(Source, Source) bool) (iter.Seq[Source], error)

ExceptEq produces the set difference of two sequences using 'equal' to compare values. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

Example

last two examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.except

fruits1 := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
	{Name: "lemon", Code: 12},
}
fruits2 := []Product{
	{Name: "APPLE", Code: 9},
}
var equal = func(p1, p2 Product) bool {
	return p1.Code == p2.Code && strings.EqualFold(p1.Name, p2.Name)
}
// Get all the elements from the first array exceptEq for the elements from the second array.
exceptEq, _ := ExceptEq(
	VarToSeq(fruits1...),
	VarToSeq(fruits2...),
	equal,
)
for product := range exceptEq {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

orange 4
lemon 12

func First

func First[Source any](source iter.Seq[Source]) (Source, error)

First returns the first element of a sequence.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.first

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19}
first, _ := First(slices.Values(numbers))
fmt.Println(first)
Output:

9

func FirstOrDefault

func FirstOrDefault[Source any](source iter.Seq[Source]) (Source, error)

FirstOrDefault returns the first element of a sequence, or a zero value if the sequence contains no elements.

Example

first two examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.firstordefault

numbers := []int{}
firstOrDefault1, _ := FirstOrDefault(slices.Values(numbers))
fmt.Println(firstOrDefault1)

months := []int{}
// Setting the default value to 1 after the query.
firstOrDefault2, _ := FirstOrDefault(VarToSeq(months...))
if firstOrDefault2 == 0 {
	firstOrDefault2 = 1
}
fmt.Printf("The value of the firstMonth1 variable is %v\n", firstOrDefault2)

// Setting the default value to 1 by using DefaultIfEmptyDef() in the query.
defaultIfEmptyDef, _ := DefaultIfEmptyDef(slices.Values(months), 1)
first, _ := First(defaultIfEmptyDef)
fmt.Printf("The value of the firstMonth2 variable is %v\n", first)
Output:

0
The value of the firstMonth1 variable is 1
The value of the firstMonth2 variable is 1

func FirstOrDefaultPred

func FirstOrDefaultPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

FirstOrDefaultPred returns the first element of the sequence that satisfies a condition or a zero value if no such element is found.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.firstordefault

names := []string{"Hartono, Tommy", "Adams, Terry", "Andersen, Henriette Thaulow", "Hedlund, Magnus", "Ito, Shu"}
firstLongName, _ := FirstOrDefaultPred(
	slices.Values(names),
	func(name string) bool { return len(name) > 20 },
)
fmt.Printf("The first long name is '%v'.\n", firstLongName)

firstVeryLongName, _ := FirstOrDefaultPred(
	slices.Values(names),
	func(name string) bool { return len(name) > 30 },
)
var what string
if firstVeryLongName == "" {
	what = "not a"
} else {
	what = "a"
}
fmt.Printf("There is %v name longer than 30 characters.\n", what)
Output:

The first long name is 'Andersen, Henriette Thaulow'.
There is not a name longer than 30 characters.

func FirstPred

func FirstPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

FirstPred returns the first element in a sequence that satisfies a specified condition.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.first

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19}
firstPred, _ := FirstPred(
	slices.Values(numbers),
	func(number int) bool { return number > 80 },
)
fmt.Println(firstPred)
Output:

92

func ForEach

func ForEach[T any](ctx context.Context, seq iter.Seq[T], action func(T) error) error

ForEach sequentially performs a specified 'action' on each element of the sequence. If 'ctx' is canceled or 'action' returns non-nil error, operation is stopped and corresponding error is returned.

func ForEachConcurrent

func ForEachConcurrent[T any](ctx context.Context, seq iter.Seq[T], action func(T) error) error

ForEachConcurrent concurrently performs a specified 'action' on each element of the sequence. If 'ctx' is canceled or 'action' returns non-nil error, operation is stopped and corresponding error is returned.

func GroupBy

func GroupBy[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key) (iter.Seq[Grouping[Key, Source]], error)

GroupBy groups the elements of a sequence according to a specified key selector function. The keys are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

Example

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/grouping-data#query-expression-syntax-example

groupBy, _ := GroupBy(
	VarToSeq(35, 44, 200, 84, 3987, 4, 199, 329, 446, 208),
	func(i int) int { return i % 2 },
)
for group := range groupBy {
	if group.Key() == 0 {
		fmt.Println("\nEven numbers:")
	} else {
		fmt.Println("\nOdd numbers:")
	}
	for i := range group.Values() {
		fmt.Println(i)
	}
}
Output:

Odd numbers:
35
3987
199
329

Even numbers:
44
200
84
4
446
208

func GroupByEq

func GroupByEq[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key,
	keyEqual func(Key, Key) bool) (iter.Seq[Grouping[Key, Source]], error)

GroupByEq groups the elements of a sequence according to a specified key selector function and compares the keys using 'keyEqual'. 'source' is enumerated immediately.

func GroupByRes

func GroupByRes[Source, Key, Result any](source iter.Seq[Source], keySelector func(Source) Key,
	resultSelector func(Key, iter.Seq[Source]) Result) (iter.Seq[Result], error)

GroupByRes groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The keys are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

Example

GroupByEx3 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.groupby

pets := []PetF{
	{Name: "Barley", Age: 8.3},
	{Name: "Boots", Age: 4.9},
	{Name: "Whiskers", Age: 1.5},
	{Name: "Daisy", Age: 4.3},
}
// Group PetF objects by the math.Floor of their Age.
// Then project a Result type from each group that consists of the Key,
// Count of the group's elements, and the minimum and maximum Age in the group.
groupByRes, _ := GroupByRes(
	slices.Values(pets),
	func(pet PetF) float64 { return math.Floor(pet.Age) },
	func(age float64, pets iter.Seq[PetF]) Result {
		count, _ := Count(pets)
		min, _ := MinSel(pets, func(pet PetF) float64 { return pet.Age })
		max, _ := MaxSel(pets, func(pet PetF) float64 { return pet.Age })
		return Result{Key: age, Count: count, Min: min, Max: max}
	},
)
for result := range groupByRes {
	fmt.Printf("\nAge group: %g\n", result.Key)
	fmt.Printf("Number of pets in this age group: %d\n", result.Count)
	fmt.Printf("Minimum age: %g\n", result.Min)
	fmt.Printf("Maximum age: %g\n", result.Max)
}
Output:

Age group: 8
Number of pets in this age group: 1
Minimum age: 8.3
Maximum age: 8.3

Age group: 4
Number of pets in this age group: 2
Minimum age: 4.3
Maximum age: 4.9

Age group: 1
Number of pets in this age group: 1
Minimum age: 1.5
Maximum age: 1.5

func GroupByResEq

func GroupByResEq[Source, Key, Result any](source iter.Seq[Source], keySelector func(Source) Key,
	resultSelector func(Key, iter.Seq[Source]) Result, keyEqual func(Key, Key) bool) (iter.Seq[Result], error)

GroupByResEq groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The keys are compared using 'keyEqual'. 'source' is enumerated immediately.

func GroupBySel

func GroupBySel[Source, Key, Element any](source iter.Seq[Source], keySelector func(Source) Key,
	elementSelector func(Source) Element) (iter.Seq[Grouping[Key, Element]], error)

GroupBySel groups the elements of a sequence according to a specified key selector function and projects the elements for each group using a specified function. The keys are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

Example

GroupByEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.groupby

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
	{Name: "Daisy", Age: 4},
}
// Group the pets using Age as the key value and selecting only the Pet's Name for each value.
groupBySel, _ := GroupBySel(
	slices.Values(pets),
	func(pet Pet) int { return pet.Age },
	func(pet Pet) string { return pet.Name },
)
// Iterate over each Grouping in the collection.
for petGroup := range groupBySel {
	// Print the key value of the Grouping.
	fmt.Println(petGroup.Key())
	// Iterate over each value in the Grouping and print the value.
	for name := range petGroup.Values() {
		fmt.Printf("  %s\n", name)
	}
}
Output:

8
  Barley
4
  Boots
  Daisy
1
  Whiskers

func GroupBySelEq

func GroupBySelEq[Source, Key, Element any](source iter.Seq[Source], keySelector func(Source) Key,
	elementSelector func(Source) Element, keyEqual func(Key, Key) bool) (iter.Seq[Grouping[Key, Element]], error)

GroupBySelEq groups the elements of a sequence according to a key selector function. The keys are compared using 'keyEqual' and each group's elements are projected using a specified function. 'source' is enumerated immediately.

func GroupBySelRes

func GroupBySelRes[Source, Key, Element, Result any](source iter.Seq[Source], keySelector func(Source) Key,
	elementSelector func(Source) Element, resultSelector func(Key, iter.Seq[Element]) Result) (iter.Seq[Result], error)

GroupBySelRes groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. The elements of each group are projected using a specified function. Key values are compared using generichelper.DeepEqual. 'source' is enumerated immediately.

Example

GroupByEx4 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.groupby

pets := []PetF{
	{Name: "Barley", Age: 8.3},
	{Name: "Boots", Age: 4.9},
	{Name: "Whiskers", Age: 1.5},
	{Name: "Daisy", Age: 4.3},
}
// Group PetF.Age values by the math.Floor of the age.
// Then project a Result type from each group that consists of the Key,
// Count of the group's elements, and the minimum and maximum Age in the group.
groupBySelRes, _ := GroupBySelRes(
	slices.Values(pets),
	func(pet PetF) float64 { return math.Floor(pet.Age) },
	func(pet PetF) float64 { return pet.Age },
	func(baseAge float64, ages iter.Seq[float64]) Result {
		count, _ := Count(ages)
		min, _ := Min(ages)
		max, _ := Max(ages)
		return Result{Key: baseAge, Count: count, Min: min, Max: max}
	},
)
for result := range groupBySelRes {
	fmt.Printf("\nAge group: %g\n", result.Key)
	fmt.Printf("Number of pets in this age group: %d\n", result.Count)
	fmt.Printf("Minimum age: %g\n", result.Min)
	fmt.Printf("Maximum age: %g\n", result.Max)
}
Output:

Age group: 8
Number of pets in this age group: 1
Minimum age: 8.3
Maximum age: 8.3

Age group: 4
Number of pets in this age group: 2
Minimum age: 4.3
Maximum age: 4.9

Age group: 1
Number of pets in this age group: 1
Minimum age: 1.5
Maximum age: 1.5

func GroupBySelResEq

func GroupBySelResEq[Source, Key, Element, Result any](source iter.Seq[Source], keySelector func(Source) Key,
	elementSelector func(Source) Element, resultSelector func(Key, iter.Seq[Element]) Result,
	keyEqual func(Key, Key) bool) (iter.Seq[Result], error)

GroupBySelResEq groups the elements of a sequence according to a specified key selector function and creates a result value from each group and its key. Key values are compared using 'keyEqual' and the elements of each group are projected using a specified function. 'source' is enumerated immediately.

func GroupJoin

func GroupJoin[Outer, Inner, Key, Result any](outer iter.Seq[Outer], inner iter.Seq[Inner], outerKeySelector func(Outer) Key,
	innerKeySelector func(Inner) Key, resultSelector func(Outer, iter.Seq[Inner]) Result) (iter.Seq[Result], error)

GroupJoin correlates the elements of two sequences based on equality of keys and groups the results. generichelper.DeepEqual is used to compare keys. 'inner' is enumerated on the first iteration over the result.

Example (Ex1)

GroupJoinEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.groupjoin

magnus := Person{Name: "Hedlund, Magnus"}
terry := Person{Name: "Adams, Terry"}
charlotte := Person{Name: "Weiss, Charlotte"}

barley := Pet{Name: "Barley", Owner: terry}
boots := Pet{Name: "Boots", Owner: terry}
whiskers := Pet{Name: "Whiskers", Owner: charlotte}
daisy := Pet{Name: "Daisy", Owner: magnus}

// Create a list where each element is an OwnerAndPets type that contains a person's name and
// a collection of names of the pets they own.
people := []Person{magnus, terry, charlotte}
pets := []Pet{barley, boots, whiskers, daisy}

groupJoin, _ := GroupJoin(
	slices.Values(people),
	slices.Values(pets),
	Identity[Person],
	func(pet Pet) Person { return pet.Owner },
	func(person Person, pets iter.Seq[Pet]) OwnerAndPets {
		return OwnerAndPets{
			OwnerName: person.Name,
			Pets:      errorhelper.Must(Select(pets, func(pet Pet) string { return pet.Name }))}
	},
)
for obj := range groupJoin {
	// Output the owner's name.
	fmt.Printf("%s:\n", obj.OwnerName)
	// Output each of the owner's pet's names.
	for pet := range obj.Pets {
		fmt.Printf("  %s\n", pet)
	}
}
Output:

Hedlund, Magnus:
  Daisy
Adams, Terry:
  Barley
  Boots
Weiss, Charlotte:
  Whiskers
Example (Ex2)

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/join-operations#query-expression-syntax-examples https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/join-operations#groupjoin

products := []Product{
	{Name: "Cola", CategoryId: 0},
	{Name: "Tea", CategoryId: 0},
	{Name: "Apple", CategoryId: 1},
	{Name: "Kiwi", CategoryId: 1},
	{Name: "Carrot", CategoryId: 2},
}
categories := []Category{
	{Id: 0, CategoryName: "Beverage"},
	{Id: 1, CategoryName: "Fruit"},
	{Id: 2, CategoryName: "Vegetable"},
}
// Join categories and product based on CategoryId and grouping result
productGroups, _ := GroupJoin(
	slices.Values(categories),
	slices.Values(products),
	func(category Category) int { return category.Id },
	func(product Product) int { return product.CategoryId },
	func(category Category, products iter.Seq[Product]) iter.Seq[Product] {
		return products
	},
)
for productGroup := range productGroups {
	fmt.Println("Group")
	for product := range productGroup {
		fmt.Printf("%8s\n", product.Name)
	}
}
Output:

Group
    Cola
     Tea
Group
   Apple
    Kiwi
Group
  Carrot

func GroupJoinEq

func GroupJoinEq[Outer, Inner, Key, Result any](outer iter.Seq[Outer], inner iter.Seq[Inner],
	outerKeySelector func(Outer) Key, innerKeySelector func(Inner) Key,
	resultSelector func(Outer, iter.Seq[Inner]) Result, keyEqual func(Key, Key) bool) (iter.Seq[Result], error)

GroupJoinEq correlates the elements of two sequences based on key equality and groups the results. 'keyEqual' is used to compare keys. 'inner' is enumerated on the first iteration over the result.

func Identity

func Identity[T any](el T) T

Identity is a selector that projects the element into itself.

func Index

func Index[Source any](source iter.Seq[Source]) (iter.Seq[generichelper.Tuple2[int, Source]], error)

Index returns a sequence that incorporates the element's index into a tuple.

func Intersect

func Intersect[Source any](first, second iter.Seq[Source]) (iter.Seq[Source], error)

Intersect produces the set intersection of two sequences using generichelper.DeepEqual to compare values. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersect

id1 := VarToSeq(44, 26, 92, 30, 71, 38)
id2 := VarToSeq(39, 59, 83, 47, 26, 4, 30)
intersect, _ := Intersect(id1, id2)
for id := range intersect {
	fmt.Println(id)
}
Output:

26
30

func IntersectBy

func IntersectBy[Source, Key any](first iter.Seq[Source], second iter.Seq[Key], keySelector func(Source) Key) (iter.Seq[Source], error)

IntersectBy produces the set intersection of two sequences according to a specified key selector function and using generichelper.DeepEqual as key equaler. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func IntersectByCmp

func IntersectByCmp[Source, Key any](first iter.Seq[Source], second iter.Seq[Key],
	keySelector func(Source) Key, compare func(Key, Key) int) (iter.Seq[Source], error)

IntersectByCmp produces the set intersection of two sequences according to a specified key selector function and using a specified key comparer. (See DistinctCmp.) 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func IntersectByEq

func IntersectByEq[Source, Key any](first iter.Seq[Source], second iter.Seq[Key],
	keySelector func(Source) Key, keyEqual func(Key, Key) bool) (iter.Seq[Source], error)

IntersectByEq produces the set intersection of two sequences according to a specified key selector function and using a specified key equaler. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func IntersectCmp

func IntersectCmp[Source any](first, second iter.Seq[Source], compare func(Source, Source) int) (iter.Seq[Source], error)

IntersectCmp produces the set intersection of two sequences using 'comparer' to compare values. (See DistinctCmp.) 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

func IntersectEq

func IntersectEq[Source any](first, second iter.Seq[Source], equal func(Source, Source) bool) (iter.Seq[Source], error)

IntersectEq produces the set intersection of two sequences using 'equal' to compare values. 'second' is enumerated on the first iteration over the result. Order of elements in the result corresponds to the order of elements in 'first'.

Example

second and third examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.intersect

store1 := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
}
store2 := []Product{
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
}
// Get the products from the first array that have duplicates in the second array.
equal := func(p1, p2 Product) bool {
	return p1.Name == p2.Name && p1.Code == p2.Code
}
intersectEq, _ := IntersectEq(slices.Values(store1), slices.Values(store2), equal)
for product := range intersectEq {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

apple 9

func Join

func Join[Outer, Inner, Key, Result any](outer iter.Seq[Outer], inner iter.Seq[Inner],
	outerKeySelector func(Outer) Key, innerKeySelector func(Inner) Key,
	resultSelector func(Outer, Inner) Result) (iter.Seq[Result], error)

Join correlates the elements of two sequences based on matching keys. generichelper.DeepEqual is used to compare keys. 'inner' is enumerated on the first iteration over the result.

Example (Ex1)

JoinEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.join

magnus := Person{Name: "Hedlund, Magnus"}
terry := Person{Name: "Adams, Terry"}
charlotte := Person{Name: "Weiss, Charlotte"}

barley := Pet{Name: "Barley", Owner: terry}
boots := Pet{Name: "Boots", Owner: terry}
whiskers := Pet{Name: "Whiskers", Owner: charlotte}
daisy := Pet{Name: "Daisy", Owner: magnus}

// Create a list of Person-Pet pairs where each element is an OwnerNameAndPetName type that contains a
// Pet's name and the name of the Person that owns the Pet.
join, _ := Join(
	VarToSeq(magnus, terry, charlotte),
	VarToSeq(barley, boots, whiskers, daisy),
	Identity[Person],
	func(pet Pet) Person { return pet.Owner },
	func(person Person, pet Pet) OwnerNameAndPetName {
		return OwnerNameAndPetName{Owner: person.Name, Pet: pet.Name}
	},
)
for obj := range join {
	fmt.Printf("%s - %s\n", obj.Owner, obj.Pet)
}
Output:

Hedlund, Magnus - Daisy
Adams, Terry - Barley
Adams, Terry - Boots
Weiss, Charlotte - Whiskers
Example (Ex2)

https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/join-operations#query-expression-syntax-examples https://learn.microsoft.com/dotnet/csharp/programming-guide/concepts/linq/join-operations#join

products := []Product{
	{Name: "Cola", CategoryId: 0},
	{Name: "Tea", CategoryId: 0},
	{Name: "Apple", CategoryId: 1},
	{Name: "Kiwi", CategoryId: 1},
	{Name: "Carrot", CategoryId: 2},
}
categories := []Category{
	{Id: 0, CategoryName: "Beverage"},
	{Id: 1, CategoryName: "Fruit"},
	{Id: 2, CategoryName: "Vegetable"},
}
// Join products and categories based on CategoryId
join, _ := Join(
	slices.Values(products),
	slices.Values(categories),
	func(product Product) int { return product.CategoryId },
	func(category Category) int { return category.Id },
	func(product Product, category Category) string {
		return fmt.Sprintf("%s - %s", product.Name, category.CategoryName)
	},
)
for item := range join {
	fmt.Println(item)
}
Output:

Cola - Beverage
Tea - Beverage
Apple - Fruit
Kiwi - Fruit
Carrot - Vegetable

func JoinEq

func JoinEq[Outer, Inner, Key, Result any](outer iter.Seq[Outer], inner iter.Seq[Inner],
	outerKeySelector func(Outer) Key, innerKeySelector func(Inner) Key,
	resultSelector func(Outer, Inner) Result, keyEqual func(Key, Key) bool) (iter.Seq[Result], error)

JoinEq correlates the elements of two sequences based on matching keys. 'keyEqual' is used to compare keys. 'inner' is enumerated on the first iteration over the result.

Similar to the keys equality functionality may be achieved using appropriate key selectors. See [TestJoinEqMust_CustomComparer] test for usage of case insensitive string keys.

func Last

func Last[Source any](source iter.Seq[Source]) (Source, error)

Last returns the last element of a sequence.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.last

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 67, 12, 19}
last, _ := Last(slices.Values(numbers))
fmt.Println(last)
Output:

19

func LastOrDefault

func LastOrDefault[Source any](source iter.Seq[Source]) (Source, error)

LastOrDefault returns the last element of a sequence or a zero value if the sequence contains no elements.

Example

first two examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.lastordefault

fruits := []string{}
last, _ := LastOrDefault(slices.Values(fruits))
if last == "" {
	fmt.Println("<string is empty>")
} else {
	fmt.Println(last)
}

daysOfMonth := []int{}
// Setting the default value to 1 after the query.
lastDay1, _ := LastOrDefault(slices.Values(daysOfMonth))
if lastDay1 == 0 {
	lastDay1 = 1
}
fmt.Printf("The value of the lastDay1 variable is %v\n", lastDay1)

// Setting the default value to 1 by using DefaultIfEmptyDef() in the query.
defaultIfEmptyDef, _ := DefaultIfEmptyDef(slices.Values(daysOfMonth), 1)
lastDay2, _ := Last(defaultIfEmptyDef)
fmt.Printf("The value of the lastDay2 variable is %d\n", lastDay2)
Output:

<string is empty>
The value of the lastDay1 variable is 1
The value of the lastDay2 variable is 1

func LastOrDefaultPred

func LastOrDefaultPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

LastOrDefaultPred returns the last element of a sequence that satisfies a condition or a zero value if no such element is found.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.lastordefault

numbers := []float64{49.6, 52.3, 51.0, 49.4, 50.2, 48.3}
last50, _ := LastOrDefaultPred(
	slices.Values(numbers),
	func(n float64) bool { return math.Round(n) == 50.0 },
)
fmt.Printf("The last number that rounds to 50 is %v.\n", last50)

last40, _ := LastOrDefaultPred(
	slices.Values(numbers),
	func(n float64) bool { return math.Round(n) == 40.0 },
)
var what string
if last40 == 0.0 {
	what = "<DOES NOT EXIST>"
} else {
	what = fmt.Sprint(last40)
}
fmt.Printf("The last number that rounds to 40 is %v.\n", what)
Output:

The last number that rounds to 50 is 50.2.
The last number that rounds to 40 is <DOES NOT EXIST>.

func LastPred

func LastPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

LastPred returns the last element of a sequence that satisfies a specified condition.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.last

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 67, 12, 19}
lastPred, _ := LastPred(
	slices.Values(numbers),
	func(number int) bool { return number > 80 },
)
fmt.Println(lastPred)
Output:

87

func Max

func Max[Source cmp.Ordered](source iter.Seq[Source]) (Source, error)

Max returns the maximum value in a sequence.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.max

longs := []int{4294967296, 466855135, 81125}
max, _ := Max(slices.Values(longs))
fmt.Printf("The largest number is %d.\n", max)
Output:

The largest number is 4294967296.

func MaxBySel

func MaxBySel[Source any, Key cmp.Ordered](source iter.Seq[Source], selector func(Source) Key) (Source, error)

MaxBySel returns the value in a sequence that produces the maximum key according to a key selector function.

Example
maxBySel1, _ := MaxBySel(
	errorhelper.Must(Range(1, 10)),
	func(i int) int { return i * i % 10 },
)
fmt.Println(maxBySel1)
maxBySel2, _ := MaxBySel(
	VarToSeq("one", "two", "three", "four", "five"),
	func(s string) int { return len(s) },
)
fmt.Println(maxBySel2)
Output:

3
three

func MaxBySelLs

func MaxBySelLs[Source, Key any](source iter.Seq[Source], selector func(Source) Key, less func(Key, Key) bool) (Source, error)

MaxBySelLs returns the value in a sequence that produces the maximum key according to a key selector function and a key less.

func MaxLs

func MaxLs[Source any](source iter.Seq[Source], less func(Source, Source) bool) (Source, error)

MaxLs returns the maximum value in a sequence using a specified less.

Example

MaxEx3 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.max

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
maxLs, _ := MaxLs(
	slices.Values(pets),
	// Compares Pets by summing each Pet's age and name length.
	func(p1, p2 Pet) bool { return p1.Age+len(p1.Name) < p2.Age+len(p2.Name) },
)
fmt.Printf("The 'maximum' animal is %s.\n", maxLs.Name)
Output:

The 'maximum' animal is Barley.

func MaxSel

func MaxSel[Source any, Result cmp.Ordered](source iter.Seq[Source], selector func(Source) Result) (Result, error)

MaxSel invokes a transform function on each element of a sequence and returns the maximum resulting value.

Example

MaxEx4 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.max

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
maxSel, _ := MaxSel(slices.Values(pets), func(pet Pet) int { return pet.Age + len(pet.Name) })
fmt.Printf("The maximum pet age plus name length is %d.\n", maxSel)
Output:

The maximum pet age plus name length is 14.

func MaxSelLs

func MaxSelLs[Source, Result any](source iter.Seq[Source], selector func(Source) Result, less func(Result, Result) bool) (Result, error)

MaxSelLs invokes a transform function on each element of a sequence and returns the maximum resulting value using a specified less.

func Min

func Min[Source cmp.Ordered](source iter.Seq[Source]) (Source, error)

Min returns the minimum value in a sequence.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.min

doubles := []float64{1.5e+104, 9e+103, -2e+103}
min, _ := Min(slices.Values(doubles))
fmt.Printf("The smallest number is %G.\n", min)
Output:

The smallest number is -2E+103.

func MinBySel

func MinBySel[Source any, Key cmp.Ordered](source iter.Seq[Source], selector func(Source) Key) (Source, error)

MinBySel returns the value in a sequence that produces the minimum key according to a key selector function.

Example
minBySel1, _ := MinBySel(
	errorhelper.Must(Range(1, 10)),
	func(i int) int { return i * i % 10 },
)
fmt.Println(minBySel1)
minBySel2, _ := MinBySel(
	VarToSeq("one", "two", "three", "four", "five"),
	func(s string) int { return len(s) },
)
fmt.Println(minBySel2)
Output:

10
one

func MinBySelLs

func MinBySelLs[Source, Key any](source iter.Seq[Source], selector func(Source) Key, less func(Key, Key) bool) (Source, error)

MinBySelLs returns the value in a sequence that produces the minimum key according to a key selector function and a key less.

func MinLs

func MinLs[Source any](source iter.Seq[Source], less func(Source, Source) bool) (Source, error)

MinLs returns the minimum value in a sequence using a specified less.

Example

MinEx3 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.min

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
minLs, _ := MinLs(
	slices.Values(pets),
	// Compares Pet's ages.
	func(p1, p2 Pet) bool { return p1.Age < p2.Age },
)
fmt.Printf("The 'minimum' animal is %s.\n", minLs.Name)
Output:

The 'minimum' animal is Whiskers.

func MinSel

func MinSel[Source any, Result cmp.Ordered](source iter.Seq[Source], selector func(Source) Result) (Result, error)

MinSel invokes a transform function on each element of a sequence and returns the minimum resulting value.

Example

MinEx4 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.min

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
minSel, _ := MinSel(slices.Values(pets), func(pet Pet) int { return pet.Age })
fmt.Printf("The youngest animal is age %d.\n", minSel)
Output:

The youngest animal is age 1.

func MinSelLs

func MinSelLs[Source, Result any](source iter.Seq[Source], selector func(Source) Result, less func(Result, Result) bool) (Result, error)

MinSelLs invokes a transform function on each element of a sequence and returns the minimum resulting value using a specified less.

func OfType

func OfType[Source, Result any](source iter.Seq[Source]) (iter.Seq[Result], error)

OfType filters the elements of a sequence based on a specified type.

func OrderBy

func OrderBy[Source cmp.Ordered](source iter.Seq[Source]) (iter.Seq[Source], error)

OrderBy sorts the elements of a sequence in ascending order.

Example
fmt.Println(StringDef[string](
	errorhelper.Must(OrderBy(VarToSeq("zero", "one", "two", "three", "four", "five"))),
))
Output:

[five four one three two zero]

func OrderByDesc

func OrderByDesc[Source cmp.Ordered](source iter.Seq[Source]) (iter.Seq[Source], error)

OrderByDesc sorts the elements of a sequence in descending order.

func OrderByDescLs

func OrderByDescLs[Source any](source iter.Seq[Source], less func(Source, Source) bool) (iter.Seq[Source], error)

OrderByDescLs sorts the elements of a sequence in descending order using a specified 'less' function.

Example

OrderByDescendingEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.orderbydescending

decimals := []float64{6.2, 8.3, 0.5, 1.3, 6.3, 9.7}
less := func(f1, f2 float64) bool {
	_, fr1 := math.Modf(f1)
	_, fr2 := math.Modf(f2)
	if math.Abs(fr1-fr2) < 0.001 {
		return f1 < f2
	}
	return fr1 < fr2
}
orderByDescLs, _ := OrderByDescLs(slices.Values(decimals), less)
for num := range orderByDescLs {
	fmt.Println(num)
}
Output:

9.7
0.5
8.3
6.3
1.3
6.2

func OrderByKey

func OrderByKey[Source any, Key cmp.Ordered](source iter.Seq[Source],
	keySelector func(Source) Key) (iter.Seq[Source], error)

OrderByKey sorts the elements of a sequence in ascending order according to a key.

func OrderByKeyDesc

func OrderByKeyDesc[Source any, Key cmp.Ordered](source iter.Seq[Source],
	keySelector func(Source) Key) (iter.Seq[Source], error)

OrderByKeyDesc sorts the elements of a sequence in descending order according to a key.

Example
fmt.Println(StringDef[string](
	errorhelper.Must(OrderByKeyDesc(
		VarToSeq("zero", "one", "two", "three", "four", "five"),
		func(s string) int { return len(s) },
	)),
))
Output:

[three zero four five one two]

func OrderByKeyDescLs

func OrderByKeyDescLs[Source, Key any](source iter.Seq[Source],
	keySelector func(Source) Key, less func(Key, Key) bool) (iter.Seq[Source], error)

OrderByKeyDescLs sorts the elements of a sequence in descending order of keys using a 'less' function.

func OrderByKeyLs

func OrderByKeyLs[Source, Key any](source iter.Seq[Source],
	keySelector func(Source) Key, less func(Key, Key) bool) (iter.Seq[Source], error)

OrderByKeyLs sorts the elements of a sequence in ascending order of keys using a specified 'less' function.

func OrderByLs

func OrderByLs[Source any](source iter.Seq[Source], less func(Source, Source) bool) (iter.Seq[Source], error)

OrderByLs sorts the elements of a sequence in ascending order using a specified 'less' function.

Example

OrderByEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.orderby

pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
orderByLs, _ := OrderByLs(slices.Values(pets), func(p1, p2 Pet) bool { return p1.Age < p2.Age })
for pet := range orderByLs {
	fmt.Printf("%s - %d\n", pet.Name, pet.Age)
}
Output:

Whiskers - 1
Boots - 4
Barley - 8

func Prepend

func Prepend[Source any](source iter.Seq[Source], element Source) (iter.Seq[Source], error)

Prepend adds a value to the beginning of the sequence.

func Range

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

Range generates a sequence of ints within a specified range.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.range#examples

// Generate a sequence of integers from 1 to 10 and then select their squares.
rnge, _ := Range(1, 10)
squares, _ := Select(rnge, func(x int) int { return x * x })
for num := range squares {
	fmt.Println(num)
}
Output:

1
4
9
16
25
36
49
64
81
100

func Repeat

func Repeat[Result any](element Result, count int) (iter.Seq[Result], error)

Repeat generates a sequence that contains one repeated value.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.repeat#examples

ss, _ := Repeat("I like programming.", 4)
for s := range ss {
	fmt.Println(s)
}
Output:

I like programming.
I like programming.
I like programming.
I like programming.

func Reverse

func Reverse[Source any](source iter.Seq[Source]) (iter.Seq[Source], error)

Reverse inverts the order of the elements in a sequence.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.reverse#examples

apple := []string{"a", "p", "p", "l", "e"}
reverse, _ := Reverse(slices.Values(apple))
for num := range reverse {
	fmt.Print(num)
}
fmt.Println()
Output:

elppa

func ReverseLess

func ReverseLess[T any](less func(T, T) bool) func(T, T) bool

ReverseLess reverses the provided 'less'.

func Select

func Select[Source, Result any](source iter.Seq[Source], selector func(Source) Result) (iter.Seq[Result], error)

Select projects each element of a sequence into a new form.

Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.select

rnge, _ := Range(1, 10)
squares, _ := Select(rnge, func(x int) int { return x * x })
for num := range squares {
	fmt.Println(num)
}
Output:

1
4
9
16
25
36
49
64
81
100
Example (Ex2)
numbers := []string{"one", "two", "three", "four", "five"}
select1, _ := Select(
	slices.Values(numbers),
	func(s string) string {
		return string(s[0]) + string(s[len(s)-1])
	},
)
fmt.Println(StringDef(select1))
select2, _ := Select(
	slices.Values(numbers),
	func(s string) string {
		runes := []rune(s)
		reversedRunes := slices.Collect(errorhelper.Must(Reverse(slices.Values(runes))))
		return string(reversedRunes)
	},
)
fmt.Println(StringDef(select2))
Output:

[oe to te fr fe]
[eno owt eerht ruof evif]

func SelectIdx

func SelectIdx[Source, Result any](source iter.Seq[Source], selector func(Source, int) Result) (iter.Seq[Result], error)

SelectIdx projects each element of a sequence into a new form by incorporating the element's index.

Example
fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
selectIdx, _ := SelectIdx(
	slices.Values(fruits),
	func(fruit string, index int) indexStr {
		return indexStr{index: index, str: fruit[:index]}
	},
)
for is := range selectIdx {
	fmt.Printf("%+v\n", is)
}
Output:

{index:0 str:}
{index:1 str:b}
{index:2 str:ma}
{index:3 str:ora}
{index:4 str:pass}
{index:5 str:grape}

func SelectMany

func SelectMany[Source, Result any](source iter.Seq[Source], selector func(Source) iter.Seq[Result]) (iter.Seq[Result], error)

SelectMany projects each element of a sequence to another sequence and flattens the resulting sequences into one sequence.

Example (Ex1)

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.concat#examples

cats := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
}
dogs := []Pet{
	{Name: "Bounder", Age: 3},
	{Name: "Snoopy", Age: 14},
	{Name: "Fido", Age: 9},
}
select1, _ := Select(slices.Values(cats), func(cat Pet) string { return cat.Name })
select2, _ := Select(slices.Values(dogs), func(dog Pet) string { return dog.Name })
selectMany, _ := SelectMany(VarToSeq(select1, select2), Identity[iter.Seq[string]])
for name := range selectMany {
	fmt.Println(name)
}
Output:

Barley
Boots
Whiskers
Bounder
Snoopy
Fido
Example (Ex2)

SelectManyEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.selectmany

petOwners := []PetOwner{
	{Name: "Higa, Sidney", Pets: []string{"Scruffy", "Sam"}},
	{Name: "Ashkenazi, Ronen", Pets: []string{"Walker", "Sugar"}},
	{Name: "Price, Vernette", Pets: []string{"Scratches", "Diesel"}},
}

// Query using SelectMany().
selectMany, _ := SelectMany(
	slices.Values(petOwners),
	func(petOwner PetOwner) iter.Seq[string] { return slices.Values(petOwner.Pets) },
)
fmt.Println("Using SelectMany():")
// Only one loop is required to iterate through the results since it is a one-dimensional collection.
for pet := range selectMany {
	fmt.Println(pet)
}

// This code shows how to use Select() instead of SelectMany().
petLists, _ := Select(
	slices.Values(petOwners),
	func(petOwner PetOwner) iter.Seq[string] {
		return slices.Values(petOwner.Pets)
	},
)
fmt.Println("\nUsing Select():")
// Notice that two loops are required to iterate through the results
// because the query returns a collection of sequences.
for petList := range petLists {
	for pet := range petList {
		fmt.Println(pet)
	}
	fmt.Println()
}
Output:

Using SelectMany():
Scruffy
Sam
Walker
Sugar
Scratches
Diesel

Using Select():
Scruffy
Sam

Walker
Sugar

Scratches
Diesel

func SelectManyColl

func SelectManyColl[Source, Collection, Result any](source iter.Seq[Source],
	collectionSelector func(Source) iter.Seq[Collection], resultSelector func(Source, Collection) Result) (iter.Seq[Result], error)

SelectManyColl projects each element of a sequence to another sequence, flattens the resulting sequences into one sequence and invokes a result selector function on each element therein.

Example

SelectManyEx3 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.selectmany

petOwners := []PetOwner{
	{Name: "Higa", Pets: []string{"Scruffy", "Sam"}},
	{Name: "Ashkenazi", Pets: []string{"Walker", "Sugar"}},
	{Name: "Price", Pets: []string{"Scratches", "Diesel"}},
	{Name: "Hines", Pets: []string{"Dusty"}},
}
// Project all pet's names together with the pet's owner.
selectManyColl, _ := SelectManyColl(
	slices.Values(petOwners),
	func(petOwner PetOwner) iter.Seq[string] {
		return slices.Values(petOwner.Pets)
	},
	func(petOwner PetOwner, petName string) OwnerAndPet {
		return OwnerAndPet{petOwner: petOwner, petName: petName}
	},
)
// Filter only pet's names that start with S.
where, _ := Where(selectManyColl,
	func(ownerAndPet OwnerAndPet) bool {
		return strings.HasPrefix(ownerAndPet.petName, "S")
	},
)
// Project the pet owner's name and the pet's name.
ownerPetNames, _ := Select(where,
	func(ownerAndPet OwnerAndPet) OwnerNameAndPetName {
		return OwnerNameAndPetName{Owner: ownerAndPet.petOwner.Name, Pet: ownerAndPet.petName}
	},
)
for ownerPetName := range ownerPetNames {
	fmt.Printf("%+v\n", ownerPetName)
}
Output:

{Owner:Higa Pet:Scruffy}
{Owner:Higa Pet:Sam}
{Owner:Ashkenazi Pet:Sugar}
{Owner:Price Pet:Scratches}

func SelectManyCollIdx

func SelectManyCollIdx[Source, Collection, Result any](source iter.Seq[Source],
	collectionSelector func(Source, int) iter.Seq[Collection], resultSelector func(Source, Collection) Result) (iter.Seq[Result], error)

SelectManyCollIdx projects each element of a sequence and its index to another sequence, flattens the resulting sequences into one sequence and invokes a result selector function on each element therein.

func SelectManyIdx

func SelectManyIdx[Source, Result any](source iter.Seq[Source], selector func(Source, int) iter.Seq[Result]) (iter.Seq[Result], error)

SelectManyIdx projects each element of a sequence and its index to another sequence and flattens the resulting sequences into one sequence.

Example

SelectManyEx2 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.selectmany

petOwners := []PetOwner{
	{Name: "Higa, Sidney", Pets: []string{"Scruffy", "Sam"}},
	{Name: "Ashkenazi, Ronen", Pets: []string{"Walker", "Sugar"}},
	{Name: "Price, Vernette", Pets: []string{"Scratches", "Diesel"}},
	{Name: "Hines, Patrick", Pets: []string{"Dusty"}},
}
// Project the items in the array by appending the index of each PetOwner
// to each pet's name in that petOwner's slice of pets.
selectManyIdx, _ := SelectManyIdx(
	slices.Values(petOwners),
	func(petOwner PetOwner, index int) iter.Seq[string] {
		return errorhelper.Must(
			Select(
				slices.Values(petOwner.Pets),
				func(pet string) string { return strconv.Itoa(index) + pet },
			),
		)
	},
)
for pet := range selectManyIdx {
	fmt.Println(pet)
}
Output:

0Scruffy
0Sam
1Walker
1Sugar
2Scratches
2Diesel
3Dusty

func SeqString

func SeqString[T any](seq iter.Seq[T]) (iter.Seq[string], error)

SeqString converts a sequence to a sequence of strings.

func SequenceEqual

func SequenceEqual[Source any](first, second iter.Seq[Source]) (bool, error)

SequenceEqual determines whether two sequences are equal by comparing the elements using generichelper.DeepEqual.

Example

SequenceEqualEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.sequenceequal

pet1 := Pet{Name: "Turbo", Age: 2}
pet2 := Pet{Name: "Peanut", Age: 8}
pets1 := []Pet{pet1, pet2}
pets2 := []Pet{pet1, pet2}
sequenceEqual, _ := SequenceEqual(slices.Values(pets1), slices.Values(pets2))
var what string
if sequenceEqual {
	what = "are"
} else {
	what = "are not"
}
fmt.Printf("The lists %s equal.\n", what)
Output:

The lists are equal.

func SequenceEqual2

func SequenceEqual2[K, V any](first, second iter.Seq2[K, V]) (bool, error)

SequenceEqual2 determines whether two sequences are equal by comparing the elements using generichelper.DeepEqual.

func SequenceEqual2Eq

func SequenceEqual2Eq[K, V any](first, second iter.Seq2[K, V], equalK func(K, K) bool, equalV func(V, V) bool) (bool, error)

SequenceEqual2Eq determines whether two sequences are equal by comparing their elements using specified equals.

func SequenceEqualEq

func SequenceEqualEq[Source any](first, second iter.Seq[Source], equal func(Source, Source) bool) (bool, error)

SequenceEqualEq determines whether two sequences are equal by comparing their elements using a specified 'equal'.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.sequenceequal

storeA := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
}
storeB := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
}
equalEq, _ := SequenceEqualEq(
	slices.Values(storeA),
	slices.Values(storeB),
	func(p1, p2 Product) bool {
		return p1.Code == p2.Code && p1.Name == p2.Name
	},
)
fmt.Printf("Equal? %t\n", equalEq)
Output:

Equal? true

func Single

func Single[Source any](source iter.Seq[Source]) (Source, error)

Single returns the only element of a sequence and returns an error if there is not exactly one element in the sequence.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.single

fruits := []string{"orange", "apple"}
fruit, err := Single(slices.Values(fruits))
if errors.Is(err, ErrMultipleElements) {
	fmt.Println("The collection does not contain exactly one element.")
} else {
	fmt.Println(fruit)
}
Output:

The collection does not contain exactly one element.
Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.single

fruits := []string{"orange"}
fruit, _ := Single(slices.Values(fruits))
fmt.Println(fruit)
Output:

orange
Example (Ex2)

third example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault

pageNumbers := []int{}
// Setting the default value to 1 by using DefaultIfEmpty() in the query.
pageNumber, _ := Single(errorhelper.Must(DefaultIfEmptyDef(slices.Values(pageNumbers), 1)))
fmt.Printf("The value of the pageNumber2 variable is %d\n", pageNumber)
Output:

The value of the pageNumber2 variable is 1

func SingleOrDefault

func SingleOrDefault[Source any](source iter.Seq[Source]) (Source, error)

SingleOrDefault returns the only element of a sequence or a zero value if the sequence is empty.

Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault

fruits := []string{"orange"}
fruit, _ := SingleOrDefault(slices.Values(fruits))
fmt.Println(fruit)
Output:

orange
Example (Ex2)

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault

fruits := []string{}
fruit, _ := SingleOrDefault(slices.Values(fruits))
var what string
if fruit == "" {
	what = "No such string!"
} else {
	what = fruit
}
fmt.Println(what)
Output:

No such string!
Example (Ex3)

third example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault

var pageNumbers []int = nil
// Setting the default value to 1 after the query.
pageNumber, _ := SingleOrDefault(slices.Values(pageNumbers))
if pageNumber == 0 {
	pageNumber = 1
}
fmt.Printf("The value of the pageNumber1 variable is %d\n", pageNumber)
Output:

The value of the pageNumber1 variable is 1

func SingleOrDefaultPred

func SingleOrDefaultPred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

SingleOrDefaultPred returns the only element of a sequence that satisfies a specified condition or a zero value if no such element exists.

Example

fourth and fifth examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.singleordefault

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
fruit1, _ := SingleOrDefaultPred(slices.Values(fruits), func(fr string) bool { return len(fr) > 10 })
fmt.Println(fruit1)

fruit2, _ := SingleOrDefaultPred(slices.Values(fruits), func(fr string) bool { return len(fr) > 15 })
var what string
if fruit2 == "" {
	what = "No such string!"
} else {
	what = fruit2
}
fmt.Println(what)
Output:

passionfruit
No such string!

func SinglePred

func SinglePred[Source any](source iter.Seq[Source], predicate func(Source) bool) (Source, error)

SinglePred returns the only element of a sequence that satisfies a specified condition.

Example

third and fourth examples from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.single

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}

fruit1, _ := SinglePred(slices.Values(fruits), func(fr string) bool { return len(fr) > 10 })
fmt.Println(fruit1)

fruit2, err := SinglePred(slices.Values(fruits), func(fr string) bool { return len(fr) > 15 })
if errors.Is(err, ErrNoMatch) {
	fmt.Println("The collection does not contain exactly one element whose length is greater than 15.")
} else {
	fmt.Println(fruit2)
}

fruit3, err := SinglePred(
	slices.Values(fruits),
	func(fr string) bool { return len(fr) > 5 },
)
if errors.Is(err, ErrMultipleMatch) {
	fmt.Println("The collection does not contain exactly one element whose length is greater than 5.")
} else {
	fmt.Println(fruit3)
}
Output:

passionfruit
The collection does not contain exactly one element whose length is greater than 15.
The collection does not contain exactly one element whose length is greater than 5.

func Skip

func Skip[Source any](source iter.Seq[Source], count int) (iter.Seq[Source], error)

Skip bypasses a specified number of elements in a sequence and then returns the remaining elements.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.skip#examples

grades := []int{59, 82, 70, 56, 92, 98, 85}
orderedGrades, _ := OrderByDesc(slices.Values(grades))
lowerGrades, _ := Skip(orderedGrades, 3)
fmt.Println("All grades except the top three are:")
for grade := range lowerGrades {
	fmt.Println(grade)
}
Output:

All grades except the top three are:
82
70
59
56

func SkipLast

func SkipLast[Source any](source iter.Seq[Source], count int) (iter.Seq[Source], error)

SkipLast returns a new sequence that contains the elements from 'source' with the last 'count' elements of the source collection omitted.

func SkipWhile

func SkipWhile[Source any](source iter.Seq[Source], predicate func(Source) bool) (iter.Seq[Source], error)

SkipWhile bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.skipwhile

grades := []int{59, 82, 70, 56, 92, 98, 85}
orderedGrades, _ := OrderByDesc(slices.Values(grades))
lowerGrades, _ := SkipWhile[int](orderedGrades, func(grade int) bool { return grade >= 80 })
fmt.Println("All grades below 80:")
for grade := range lowerGrades {
	fmt.Println(grade)
}
Output:

All grades below 80:
70
59
56

func SkipWhileIdx

func SkipWhileIdx[Source any](source iter.Seq[Source], predicate func(Source, int) bool) (iter.Seq[Source], error)

SkipWhileIdx bypasses elements in a sequence as long as a specified condition is true and then returns the remaining elements. The element's index is used in the logic of the predicate function.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.skipwhile

amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500}
skipWhileIdx, _ := SkipWhileIdx(slices.Values(amounts), func(amount, index int) bool { return amount > index*1000 })
for amount := range skipWhileIdx {
	fmt.Println(amount)
}
Output:

4000
1500
5500

func StringDef

func StringDef[T any](seq iter.Seq[T]) string

StringDef returns string representation of a sequence using default formatting. If 'seq' is nil, empty string is returned.

func StringDef2

func StringDef2[K, V any](seq2 iter.Seq2[K, V]) string

StringDef2 returns string representation of a sequence using default formatting. If 'seq2' is nil, empty string is returned.

func StringFmt

func StringFmt[T any](seq iter.Seq[T], sep, lrim, rrim, ledge, redge string) string

StringFmt returns string representation of a sequence:

  • if 'seq' is nil, empty string is returned;
  • if 'T' implements fmt.Stringer, it is used to convert each element to string;
  • 'sep' separates elements;
  • 'lrim' and 'rrim' surround each element;
  • 'ledge' and 'redge' surround the whole string.

func StringFmt2

func StringFmt2[K, V any](seq2 iter.Seq2[K, V], psep, esep, lrim, rrim, ledge, redge string) string

StringFmt2 returns string representation of a sequence:

  • if 'seq2' is nil, empty string is returned;
  • if 'T' implements fmt.Stringer, it is used to convert each element to string;
  • 'psep' separates pair of values;
  • 'esep' separates elements;
  • 'lrim' and 'rrim' surround each element;
  • 'ledge' and 'redge' surround the whole string.

func Strings

func Strings[T any](seq iter.Seq[T]) ([]string, error)

Strings returns a sequence contents as a slice of strings.

func Sum

func Sum[Source constraints.Integer | constraints.Float](source iter.Seq[Source]) (Source, error)

Sum computes the sum of a sequence of constraints.Integer or constraints.Float values.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.sum

numbers := []float64{43.68, 1.25, 583.7, 6.5}
sum, _ := Sum(slices.Values(numbers))
fmt.Printf("The sum of the numbers is %g.\n", sum)
Output:

The sum of the numbers is 635.13.

func SumSel

func SumSel[Source any, Result constraints.Integer | constraints.Float](source iter.Seq[Source],
	selector func(Source) Result) (Result, error)

SumSel computes the sum of a sequence of constraints.Integer or constraints.Float values that are obtained by invoking a transform function on each element of the input sequence.

Example

SumEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.sum

packages := []Package{
	{Company: "Coho Vineyard", Weight: 25.2},
	{Company: "Lucerne Publishing", Weight: 18.7},
	{Company: "Wingtip Toys", Weight: 6.0},
	{Company: "Adventure Works", Weight: 33.8},
}
totalWeight, _ := SumSel(
	slices.Values(packages),
	func(pkg Package) float64 { return pkg.Weight },
)
fmt.Printf("The total weight of the packages is: %.1f\n", totalWeight)
Output:

The total weight of the packages is: 83.7

func Take

func Take[Source any](source iter.Seq[Source], count int) (iter.Seq[Source], error)

Take returns a specified number of contiguous elements from the start of a sequence.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.take

grades := []int{59, 82, 70, 56, 92, 98, 85}
orderedGrades, _ := OrderByDesc(slices.Values(grades))
topThreeGrades, _ := Take[int](orderedGrades, 3)
fmt.Println("The top three grades are:")
for grade := range topThreeGrades {
	fmt.Println(grade)
}
Output:

The top three grades are:
98
92
85

func TakeLast

func TakeLast[Source any](source iter.Seq[Source], count int) (iter.Seq[Source], error)

TakeLast returns a new iter.Seq that contains the last 'count' elements from 'source'.

func TakeWhile

func TakeWhile[Source any](source iter.Seq[Source], predicate func(Source) bool) (iter.Seq[Source], error)

TakeWhile returns elements from a sequence as long as a specified condition is true.

Example

second example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.takewhile

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
takeWhile, _ := TakeWhile(
	slices.Values(fruits),
	func(fruit string) bool { return fruit != "orange" },
)
for fruit := range takeWhile {
	fmt.Println(fruit)
}
Output:

apple
banana
mango

func TakeWhileIdx

func TakeWhileIdx[Source any](source iter.Seq[Source], predicate func(Source, int) bool) (iter.Seq[Source], error)

TakeWhileIdx returns elements from a sequence as long as a specified condition is true. The element's index is used in the logic of the predicate function.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.takewhile

fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"}
takeWhileIdx, _ := TakeWhileIdx(
	slices.Values(fruits),
	func(fruit string, index int) bool {
		return len(fruit) >= index
	},
)
for fruit := range takeWhileIdx {
	fmt.Println(fruit)
}
Output:

apple
passionfruit
banana
mango
orange
blueberry

func ThenLess

func ThenLess[T any](less1, less2 func(T, T) bool) func(T, T) bool

ThenLess combines two less functions. At first 'less1' is applied to 'x' and 'y', if they appear different the result is returned. Otherwise, the result of 'less2' is returned.

func ToMap

func ToMap[Source any, Key comparable](source iter.Seq[Source], keySelector func(Source) Key) (map[Key]Source, error)

ToMap creates a map from a sequence according to a specified key selector function.

Example

ToDictionaryEx1 example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.todictionary

packages := []Package{
	{Company: "Coho Vineyard", Weight: 25.2, TrackingNumber: 89453312},
	{Company: "Lucerne Publishing", Weight: 18.7, TrackingNumber: 89112755},
	{Company: "Wingtip Toys", Weight: 6.0, TrackingNumber: 299456122},
	{Company: "Adventure Works", Weight: 33.8, TrackingNumber: 4665518773},
}
// Create a map of Package objects, using TrackingNumber as the key.
dictionary, _ := ToMap(
	slices.Values(packages),
	func(p Package) int64 { return p.TrackingNumber },
)
for k, p := range dictionary {
	fmt.Printf("Key %d: %s, %g pounds\n", k, p.Company, p.Weight)
}
Output:

Key 89453312: Coho Vineyard, 25.2 pounds
Key 89112755: Lucerne Publishing, 18.7 pounds
Key 299456122: Wingtip Toys, 6 pounds
Key 4665518773: Adventure Works, 33.8 pounds

func ToMapSel

func ToMapSel[Source any, Key comparable, Element any](source iter.Seq[Source],
	keySelector func(Source) Key, elementSelector func(Source) Element) (map[Key]Element, error)

ToMapSel creates a map from a sequence according to specified key selector and element selector functions.

Since Go's map does not support custom equaler to determine equality of the keys, LINQ's key comparer is not implemented. Similar to the keys equality functionality may be achieved using appropriate key selector. Example of custom key selector that mimics case-insensitive equaler for string keys is presented in [TestCustomSelector_string_string_int].

func Union

func Union[Source any](first, second iter.Seq[Source]) (iter.Seq[Source], error)

Union produces the set union of two sequences using generichelper.DeepEqual to compare values.

Example

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.union

union, _ := Union(VarToSeq(5, 3, 9, 7, 5, 9, 3, 7), VarToSeq(8, 3, 6, 4, 4, 9, 1, 0))
for num := range union {
	fmt.Printf("%d ", num)
}
Output:

5 3 9 7 8 6 4 1 0

func UnionBy

func UnionBy[Source, Key any](first, second iter.Seq[Source], keySelector func(Source) Key) (iter.Seq[Source], error)

UnionBy produces the set union of two sequences according to a specified key selector function and using generichelper.DeepEqual as key equaler.

func UnionByCmp

func UnionByCmp[Source, Key any](first, second iter.Seq[Source],
	keySelector func(Source) Key, compare func(Key, Key) int) (iter.Seq[Source], error)

UnionByCmp produces the set union of two sequences according to a specified key selector function and using a specified key comparer. (See DistinctCmp.)

func UnionByEq

func UnionByEq[Source, Key any](first, second iter.Seq[Source],
	keySelector func(Source) Key, keyEqual func(Key, Key) bool) (iter.Seq[Source], error)

UnionByEq produces the set union of two sequences according to a specified key selector function and using a specified key equaler.

func UnionCmp

func UnionCmp[Source any](first, second iter.Seq[Source], compare func(Source, Source) int) (iter.Seq[Source], error)

UnionCmp produces the set union of two sequences using 'comparer' to compare values. (See DistinctCmp.)

func UnionEq

func UnionEq[Source any](first, second iter.Seq[Source], equal func(Source, Source) bool) (iter.Seq[Source], error)

UnionEq produces the set union of two sequences using 'equal' to compare values.

Example

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.union

store1 := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
}
store2 := []Product{
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
}
//Get the products from the both arrays excluding duplicates.
equal := func(p1, p2 Product) bool { return p1.Code == p2.Code && p1.Name == p2.Name }
unionEq, _ := UnionEq(slices.Values(store1), slices.Values(store2), equal)
for product := range unionEq {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

apple 9
orange 4
lemon 12

func VarToSeq

func VarToSeq[E any](s ...E) iter.Seq[E]

VarToSeq returns an iterator over the variadic parameter elements.

func Where

func Where[Source any](source iter.Seq[Source], predicate func(Source) bool) (iter.Seq[Source], error)

Where filters a sequence of values based on a predicate.

Example (Ex1)

first example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.where

fruits := []string{"apple", "passionfruit", "banana", "mango", "orange", "blueberry", "grape", "strawberry"}
where, _ := Where(
	slices.Values(fruits),
	func(fruit string) bool { return len(fruit) < 6 },
)
for fruit := range where {
	fmt.Println(fruit)
}
Output:

apple
mango
grape
Example (Ex2)
range1, _ := Range(1, 10)
where1, _ := Where(
	range1,
	func(i int) bool { return i%2 == 0 },
)
fmt.Println(StringDef(where1))
where2, _ := Where(
	VarToSeq("one", "two", "three", "four", "five"),
	func(s string) bool { return strings.HasSuffix(s, "e") },
)
fmt.Println(StringDef(where2))
Output:

[2 4 6 8 10]
[one three five]

func WhereIdx

func WhereIdx[Source any](source iter.Seq[Source], predicate func(Source, int) bool) (iter.Seq[Source], error)

WhereIdx filters a sequence of values based on a predicate. Each element's index is used in the logic of the predicate function.

Example (Ex1)

last example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.where

numbers := []int{0, 30, 20, 15, 90, 85, 40, 75}
whereIdx, _ := WhereIdx(
	slices.Values(numbers),
	func(number, index int) bool { return number <= index*10 },
)
for number := range whereIdx {
	fmt.Println(number)
}
Output:

0
20
15
40
Example (Ex2)
whereIdx1, _ := WhereIdx(
	VarToSeq("one", "two", "three", "four", "five"),
	func(s string, i int) bool { return len(s) == i },
)
fmt.Println(StringDef(whereIdx1))
reverse2, _ := Reverse(VarToSeq("one", "two", "three", "four", "five"))
whereIdx2, _ := WhereIdx(
	reverse2,
	func(s string, i int) bool { return len(s) == i },
)
fmt.Println(StringDef(whereIdx2))
orderBy, _ := OrderBy(VarToSeq("one", "two", "three", "four", "five"))
whereIdx3, _ := WhereIdx(
	orderBy,
	func(s string, i int) bool { return len(s) > i },
)
fmt.Println(StringDef(whereIdx3))
Output:

[five]
[two]
[five four one three]

func Zip

func Zip[First, Second, Result any](first iter.Seq[First], second iter.Seq[Second],
	resultSelector func(First, Second) Result) (iter.Seq[Result], error)

Zip applies a specified function to the corresponding elements of two sequences, producing a sequence of the results.

Example

example from https://learn.microsoft.com/dotnet/api/system.linq.enumerable.zip

numbers := []int{1, 2, 3, 4}
words := []string{"one", "two", "three"}
zip, _ := Zip(slices.Values(numbers), slices.Values(words),
	func(first int, second string) string { return fmt.Sprintf("%d %s", first, second) },
)
for item := range zip {
	fmt.Println(item)
}
Output:

1 one
2 two
3 three

Types

type Counter

type Counter interface {
	// Count returns the number of elements contained in the sequence.
	Count() int
}

Counter is the interface that wraps the Count method.

type Grouping

type Grouping[Key, Element any] struct {
	// contains filtered or unexported fields
}

Grouping represents a collection of objects that have a common key.

func (*Grouping[Key, Element]) Key

func (gr *Grouping[Key, Element]) Key() Key

Key gets the key of the Grouping.

func (*Grouping[Key, Element]) Values

func (gr *Grouping[Key, Element]) Values() iter.Seq[Element]

Values returns a sequence of values in the Grouping.

type Itemer

type Itemer[T any] interface {
	// Item returns the element at the specified index in the sequence.
	Item(int) T
}

Itemer is the interface that wraps the Item method.

type Lookup

type Lookup[Key, Element any] struct {

	// KeyEqual is an equaler for groupings' keys.
	KeyEqual func(Key, Key) bool
	// contains filtered or unexported fields
}

Lookup represents a collection of keys each mapped to one or more values.

func ToLookup

func ToLookup[Source, Key any](source iter.Seq[Source], keySelector func(Source) Key) (*Lookup[Key, Source], error)

ToLookup creates a Lookup from a sequence according to a specified key selector function. generichelper.DeepEqual is used to compare keys. 'source' is enumerated immediately.

func ToLookupEq

func ToLookupEq[Source, Key any](source iter.Seq[Source],
	keySelector func(Source) Key, keyEqual func(Key, Key) bool) (*Lookup[Key, Source], error)

ToLookupEq creates a Lookup from a sequence according to a specified key selector function and a key equaler. 'source' is enumerated immediately.

func ToLookupSel

func ToLookupSel[Source, Key, Element any](source iter.Seq[Source],
	keySelector func(Source) Key, elementSelector func(Source) Element) (*Lookup[Key, Element], error)

ToLookupSel creates a Lookup from a according to specified key selector and element selector functions. 'source' is enumerated immediately.

Example

LookupExample from https://learn.microsoft.com/dotnet/api/system.linq.Lookup-2#examples

// Create a list of Packages to put into a Lookup data structure.
packages := []Package{
	{Company: "Coho Vineyard", Weight: 25.2, TrackingNumber: 89453312},
	{Company: "Lucerne Publishing", Weight: 18.7, TrackingNumber: 89112755},
	{Company: "Wingtip Toys", Weight: 6.0, TrackingNumber: 299456122},
	{Company: "Contoso Pharmaceuticals", Weight: 9.3, TrackingNumber: 670053128},
	{Company: "Wide World Importers", Weight: 33.8, TrackingNumber: 4665518773},
}
// Create a Lookup to organize the packages.
// Use the first character of Company as the key value.
// Select Company appended to TrackingNumber for each element value in the Lookup.
lookup, _ := ToLookupSel(
	slices.Values(packages),
	func(p Package) rune {
		return []rune(p.Company)[0]
	},
	func(p Package) string {
		return fmt.Sprintf("%s %d", p.Company, p.TrackingNumber)
	},
)

// Iterate through each Grouping in the Lookup and output the contents.
for _, packageGroup := range lookup.groupings {
	// Print the key value of the Grouping.
	fmt.Println(string(packageGroup.Key()))
	// Iterate through each value in the Grouping and print its value.
	for str := range packageGroup.Values() {
		fmt.Printf("    %s\n", str)
	}
}

// Get the number of key-collection pairs in the Lookup.
count := lookup.Count()
fmt.Printf("\n%d\n", count)

// Select a collection of Packages by indexing directly into the Lookup.
cgroup := lookup.Item('C')
// Output the results.
fmt.Println("\nPackages that have a key of 'C'")
for str := range cgroup {
	fmt.Println(str)
}

// Determine if there is a key with the value 'G' in the Lookup.
hasG := lookup.Contains('G')
fmt.Printf("\n%t\n", hasG)
Output:

C
    Coho Vineyard 89453312
    Contoso Pharmaceuticals 670053128
L
    Lucerne Publishing 89112755
W
    Wingtip Toys 299456122
    Wide World Importers 4665518773

3

Packages that have a key of 'C'
Coho Vineyard 89453312
Contoso Pharmaceuticals 670053128

false

func ToLookupSelEq

func ToLookupSelEq[Source, Key, Element any](source iter.Seq[Source],
	keySelector func(Source) Key, elementSelector func(Source) Element, keyEqual func(Key, Key) bool) (*Lookup[Key, Element], error)

ToLookupSelEq creates a Lookup from a sequence according to a specified key selector function, an element selector function and a key equaler. 'source' is enumerated immediately.

func (*Lookup[Key, Element]) Add

func (lk *Lookup[Key, Element]) Add(key Key, el Element)

Add adds element 'el' with specified 'key' to 'lk'

func (*Lookup[Key, Element]) Contains

func (lk *Lookup[Key, Element]) Contains(key Key) bool

Contains determines whether a specified key is in the Lookup.

func (*Lookup[Key, Element]) Count

func (lk *Lookup[Key, Element]) Count() int

Count gets the number of key/value collection pairs in the Lookup.

func (*Lookup[Key, Element]) EqualTo

func (lk *Lookup[Key, Element]) EqualTo(lk2 *Lookup[Key, Element]) bool

EqualTo determines whether the current Lookup is equal to a specified Lookup. Keys equality comparers do not participate in equality verification, since non-nil funcs are always not deeply equal.

func (*Lookup[Key, Element]) Item

func (lk *Lookup[Key, Element]) Item(key Key) iter.Seq[Element]

Item gets the collection of values indexed by a specified key.

type Slicer

type Slicer[T any] interface {
	// Slice returns the sequence contents as a slice.
	Slice() []T
}

Slicer is the interface that wraps the Slice method.

Jump to

Keyboard shortcuts

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