linq

package module
v3.0.0+incompatible Latest Latest
Warning

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

Go to latest
Published: Jan 10, 2017 License: Apache-2.0 Imports: 5 Imported by: 109

README

go-linq GoDoc Build Status Coverage Status Go Report Card

A powerful language integrated query (LINQ) library for Go.

  • Written in vanilla Go, no dependencies!
  • Complete lazy evaluation with iterator pattern
  • Safe for concurrent use
  • Supports generic functions to make your code cleaner and free of type assertions
  • Supports arrays, slices, maps, strings, channels and custom collections

Installation

$ go get github.com/ahmetalpbalkan/go-linq

We recommend using a dependency manager (e.g. govendor or godep) to maintain a local copy of this package in your project.

⚠ ⚠ go-linq has recently introduced breaking API changes with v2.0.0. See release notes for details. v2.0.0 comes with a refined interface, dramatically increased performance and memory efficiency, and new features such as lazy evaluation (read more).

The old version is still available in archive/0.9 branch and tagged as 0.9 as well. If you are using go-linq, please vendor a copy of it in your source tree to avoid getting broken by upstream changes.

Quickstart

Usage is as easy as chaining methods like:

From(slice) .Where(predicate) .Select(selector) .Union(data)

Example 1: Find all owners of cars manufactured after 2015

import . "github.com/ahmetalpbalkan/go-linq"
	
type Car struct {
    year int
    owner, model string
}

...


var owners []string

From(cars).Where(func(c interface{}) bool {
	return c.(Car).year >= 2015
}).Select(func(c interface{}) interface{} {
	return c.(Car).owner
}).ToSlice(&owners)

Or, you can use generic functions, like WhereT and SelectT to simplify your code (at a performance penalty):

var owners []string

From(cars).WhereT(func(c Car) bool {
	return c.year >= 2015
}).SelectT(func(c Car) string {
	return c.owner
}).ToSlice(&owners)	

Example 2: Find the author who has written the most books

import . "github.com/ahmetalpbalkan/go-linq"
	
type Book struct {
	id      int
	title   string
	authors []string
}

author := From(books).SelectMany( // make a flat array of authors
	func(book interface{}) Query {
		return From(book.(Book).authors)
	}).GroupBy( // group by author
	func(author interface{}) interface{} {
		return author // author as key
	}, func(author interface{}) interface{} {
		return author // author as value
	}).OrderByDescending( // sort groups by its length
	func(group interface{}) interface{} {
		return len(group.(Group).Group)
	}).Select( // get authors out of groups
	func(group interface{}) interface{} {
		return group.(Group).Key
	}).First() // take the first author

Example 3: Implement a custom method that leaves only values greater than the specified threshold

type MyQuery Query

func (q MyQuery) GreaterThan(threshold int) Query {
	return Query{
		Iterate: func() Iterator {
			next := q.Iterate()

			return func() (item interface{}, ok bool) {
				for item, ok = next(); ok; item, ok = next() {
					if item.(int) > threshold {
						return
					}
				}

				return
			}
		},
	}
}

result := MyQuery(Range(1,10)).GreaterThan(5).Results()

Generic Functions

Although Go doesn't implement generics, with some reflection tricks, you can use go-linq without typing interface{}s and type assertions. This will introduce a performance penalty (5x-10x slower) but will yield in a cleaner and more readable code.

Methods with T suffix (such as WhereT) accept functions with generic types. So instead of

.Select(func(v interface{}) interface{} {...})

you can type:

.SelectT(func(v YourType) YourOtherType {...})

This will make your code free of interface{} and type assertions.

Example 4: "MapReduce" in a slice of string sentences to list the top 5 most used words using generic functions

var results []string

From(sentences).
	// split sentences to words
	SelectManyT(func(sentence string) Query {
		return From(strings.Split(sentence, " "))
	}).
	// group the words
	GroupByT( 
		func(word string) string { return word },
		func(word string) string { return word },
	).
	// order by count
	OrderByDescendingT(func(wordGroup Group) int {
		return len(wordGroup.Group)
	}).
	// order by the word
	ThenByT(func(wordGroup Group) string {
		return wordGroup.Key.(string)
	}).
	Take(5).  // take the top 5
	// project the words using the index as rank
	SelectIndexedT(func(index int, wordGroup Group) string {
		return fmt.Sprintf("Rank: #%d, Word: %s, Counts: %d", index+1, wordGroup.Key, len(wordGroup.Group))
	}).
	ToSlice(&results)

More examples can be found in the documentation.

Release Notes

v3.0.0 (2017-01-10)
* Breaking change: ToSlice() now overwrites existing slice starting
  from index 0 and grows/reslices it as needed.
* Generic methods support (thanks @cleitonmarx!)
  - Accepting parametrized functions was originally proposed in #26
  - You can now avoid type assertions and interface{}s
  - Functions with generic methods are named as "MethodNameT" and
    signature for the existing LINQ methods are unchanged.
* Added ForEach(), ForEachIndexed() and AggregateWithSeedBy().

v2.0.0 (2016-09-02)
* IMPORTANT: This release is a BREAKING CHANGE. The old version
  is archived at the 'archive/0.9' branch or the 0.9 tags.
* A COMPLETE REWRITE of go-linq with better performance and memory
  efficiency. (thanks @kalaninja!)
* API has significantly changed. Most notably:
  - linq.T removed in favor of interface{}
  - library methods no longer return errors 
  - PLINQ removed for now (see channels support)
  - support for channels, custom collections and comparables

v0.9-rc4
* GroupBy()

v0.9-rc3.2
* bugfix: All() iterating over values instead of indices

v0.9-rc3.1
* bugfix: modifying result slice affects subsequent query methods

v0.9-rc3
* removed FirstOrNil, LastOrNil, ElementAtOrNil methods 

v0.9-rc2.5
* slice-accepting methods accept slices of any type with reflections

v0.9-rc2
* parallel linq (plinq) implemented
* Queryable separated into Query & ParallelQuery
* fixed early termination for All

v0.9-rc1
* many linq methods are implemented
* methods have error handling support
* type assertion limitations are unresolved
* travis-ci.org build integrated
* open sourced on github, master & dev branches

Documentation

Overview

Package linq provides methods for querying and manipulating slices, arrays, maps, strings, channels and collections.

Authors: Alexander Kalankhodzhaev (kalan), Ahmet Alp Balkan, Cleiton Marques Souza.

Index

Examples

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Comparable

type Comparable interface {
	CompareTo(Comparable) int
}

Comparable is an interface that has to be implemented by a custom collection elememts in order to work with linq.

Example:

func (f foo) CompareTo(c Comparable) int {
	a, b := f.f1, c.(foo).f1

	if a < b {
		return -1
	} else if a > b {
		return 1
	}

	return 0
}

type Group

type Group struct {
	Key   interface{}
	Group []interface{}
}

Group is a type that is used to store the result of GroupBy method.

type Iterable

type Iterable interface {
	Iterate() Iterator
}

Iterable is an interface that has to be implemented by a custom collection in order to work with linq.

type Iterator

type Iterator func() (item interface{}, ok bool)

Iterator is an alias for function to iterate over data.

type KeyValue

type KeyValue struct {
	Key   interface{}
	Value interface{}
}

KeyValue is a type that is used to iterate over a map (if query is created from a map). This type is also used by ToMap() method to output result of a query into a map.

Example
m := make(map[int]bool)
m[10] = true

fmt.Println(From(m).Results())
Output:

[{10 true}]
Example (Second)
input := []KeyValue{
	{10, true},
}

m := make(map[int]bool)
From(input).
	ToMap(&m)

fmt.Println(m)
Output:

map[10:true]

type OrderedQuery

type OrderedQuery struct {
	Query
	// contains filtered or unexported fields
}

OrderedQuery is the type returned from OrderBy, OrderByDescending ThenBy and ThenByDescending functions.

func (OrderedQuery) Distinct

func (oq OrderedQuery) Distinct() OrderedQuery

Distinct method returns distinct elements from a collection. The result is an ordered collection that contains no duplicate values.

NOTE: Distinct method on OrderedQuery type has better performance than Distinct method on Query type.

Example

The following code example demonstrates how to use Distinct to return distinct elements from a slice of integers.

ages := []int{21, 46, 46, 55, 17, 21, 55, 55}

var distinctAges []int
From(ages).
	OrderBy(
		func(item interface{}) interface{} { return item },
	).
	Distinct().
	ToSlice(&distinctAges)

fmt.Println(distinctAges)
Output:

[17 21 46 55]

func (OrderedQuery) ThenBy

func (oq OrderedQuery) ThenBy(
	selector func(interface{}) interface{}) OrderedQuery

ThenBy performs a subsequent ordering of the elements in a collection in ascending order. This method enables you to specify multiple sort criteria by applying any number of ThenBy or ThenByDescending methods.

Example

The following code example demonstrates how to use ThenBy to perform a secondary ordering of the elements in a slice.

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

// Sort the strings first by their length and then
//alphabetically by passing the identity selector function.
var query []string
From(fruits).
	OrderBy(
		func(fruit interface{}) interface{} { return len(fruit.(string)) },
	).
	ThenBy(
		func(fruit interface{}) interface{} { return fruit },
	).
	ToSlice(&query)

for _, fruit := range query {
	fmt.Println(fruit)
}
Output:

apple
grape
mango
banana
orange
blueberry
raspberry
passionfruit

func (OrderedQuery) ThenByDescending

func (oq OrderedQuery) ThenByDescending(selector func(interface{}) interface{}) OrderedQuery

ThenByDescending performs a subsequent ordering of the elements in a collection in descending order. This method enables you to specify multiple sort criteria by applying any number of ThenBy or ThenByDescending methods.

Example

The following code example demonstrates how to use ThenByDescending to perform a secondary ordering of the elements in a slice in descending order.

fruits := []string{"apPLe", "baNanA", "apple", "APple", "orange", "BAnana", "ORANGE", "apPLE"}

// Sort the strings first ascending by their length and
// then descending using a custom case insensitive comparer.
var query []string
From(fruits).
	OrderBy(
		func(fruit interface{}) interface{} { return len(fruit.(string)) },
	).
	ThenByDescending(
		func(fruit interface{}) interface{} { return fruit.(string)[0] },
	).
	ToSlice(&query)

for _, fruit := range query {
	fmt.Println(fruit)
}
Output:

apPLe
apPLE
apple
APple
orange
baNanA
ORANGE
BAnana

func (OrderedQuery) ThenByDescendingT

func (oq OrderedQuery) ThenByDescendingT(selectorFn interface{}) OrderedQuery

ThenByDescendingT is the typed version of ThenByDescending.

  • selectorFn is of type "func(TSource) TKey"

NOTE: ThenByDescending has better performance than ThenByDescendingT.

Example

The following code example demonstrates how to use ThenByDescendingT to perform a order in a slice of dates by year, and then by month descending.

dates := []time.Time{
	time.Date(2015, 3, 23, 0, 0, 0, 0, time.Local),
	time.Date(2014, 7, 11, 0, 0, 0, 0, time.Local),
	time.Date(2013, 5, 4, 0, 0, 0, 0, time.Local),
	time.Date(2015, 1, 2, 0, 0, 0, 0, time.Local),
	time.Date(2015, 7, 10, 0, 0, 0, 0, time.Local),
}

var orderedDates []time.Time
From(dates).
	OrderByT(
		func(date time.Time) int {
			return date.Year()
		}).
	ThenByDescendingT(
		func(date time.Time) int { return int(date.Month()) },
	).
	ToSlice(&orderedDates)

for _, date := range orderedDates {
	fmt.Println(date.Format("2006-Jan-02"))
}
Output:

2013-May-04
2014-Jul-11
2015-Jul-10
2015-Mar-23
2015-Jan-02

func (OrderedQuery) ThenByT

func (oq OrderedQuery) ThenByT(selectorFn interface{}) OrderedQuery

ThenByT is the typed version of ThenBy.

  • selectorFn is of type "func(TSource) TKey"

NOTE: ThenBy has better performance than ThenByT.

Example

The following code example demonstrates how to use ThenByT to perform a orders in a slice of dates by year, and then by day.

dates := []time.Time{
	time.Date(2015, 3, 23, 0, 0, 0, 0, time.Local),
	time.Date(2014, 7, 11, 0, 0, 0, 0, time.Local),
	time.Date(2013, 5, 4, 0, 0, 0, 0, time.Local),
	time.Date(2015, 1, 2, 0, 0, 0, 0, time.Local),
	time.Date(2015, 7, 10, 0, 0, 0, 0, time.Local),
}

var orderedDates []time.Time
From(dates).
	OrderByT(
		func(date time.Time) int { return date.Year() },
	).
	ThenByT(
		func(date time.Time) int { return int(date.Day()) },
	).
	ToSlice(&orderedDates)

for _, date := range orderedDates {
	fmt.Println(date.Format("2006-Jan-02"))
}
Output:

2013-May-04
2014-Jul-11
2015-Jan-02
2015-Jul-10
2015-Mar-23

type Query

type Query struct {
	Iterate func() Iterator
}

Query is the type returned from query functions. It can be iterated manually as shown in the example.

Example
query := From([]int{1, 2, 3, 4, 5}).Where(func(i interface{}) bool {
	return i.(int) <= 3
})

next := query.Iterate()
for item, ok := next(); ok; item, ok = next() {
	fmt.Println(item)
}
Output:

1
2
3

func From

func From(source interface{}) Query

From initializes a linq query with passed slice, array or map as the source. String, channel or struct implementing Iterable interface can be used as an input. In this case From delegates it to FromString, FromChannel and FromIterable internally.

func FromChannel

func FromChannel(source <-chan interface{}) Query

FromChannel initializes a linq query with passed channel, linq iterates over channel until it is closed.

func FromIterable

func FromIterable(source Iterable) Query

FromIterable initializes a linq query with custom collection passed. This collection has to implement Iterable interface, linq iterates over items, that has to implement Comparable interface or be basic types.

func FromString

func FromString(source string) Query

FromString initializes a linq query with passed string, linq iterates over runes of string.

func Range

func Range(start, count int) Query

Range generates a sequence of integral numbers within a specified range.

Example

The following code example demonstrates how to use Range to generate a slice of values.

// Generate a slice of integers from 1 to 10
// and then select their squares.
var squares []int
Range(1, 10).
	SelectT(
		func(x int) int { return x * x },
	).
	ToSlice(&squares)

for _, num := range squares {
	fmt.Println(num)
}
Output:

1
4
9
16
25
36
49
64
81
100

func Repeat

func Repeat(value interface{}, count int) Query

Repeat generates a sequence that contains one repeated value.

Example

The following code example demonstrates how to use Repeat to generate a slice of a repeated value.

var slice []string
Repeat("I like programming.", 5).
	ToSlice(&slice)

for _, str := range slice {
	fmt.Println(str)
}
Output:

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

func (Query) Aggregate

func (q Query) Aggregate(f func(interface{}, interface{}) interface{}) interface{}

Aggregate applies an accumulator function over a sequence.

Aggregate method makes it simple to perform a calculation over a sequence of values. This method works by calling f() one time for each element in source except the first one. Each time f() is called, Aggregate passes both the element from the sequence and an aggregated value (as the first argument to f()). The first element of source is used as the initial aggregate value. The result of f() replaces the previous aggregated value.

Aggregate returns the final result of f().

Example

The following code example demonstrates how to use Aggregate function

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

// Determine which string in the slice is the longest.
longestName := From(fruits).
	Aggregate(
		func(r interface{}, i interface{}) interface{} {
			if len(r.(string)) > len(i.(string)) {
				return r
			}
			return i
		},
	)

fmt.Println(longestName)
Output:

passionfruit

func (Query) AggregateT

func (q Query) AggregateT(f interface{}) interface{}

AggregateT is the typed version of Aggregate.

  • f is of type: func(TSource, TSource) TSource

NOTE: Aggregate has better performance than AggregateT.

Example

The following code example demonstrates how to reverse the order of words in a string using AggregateT.

sentence := "the quick brown fox jumps over the lazy dog"
// Split the string into individual words.
words := strings.Split(sentence, " ")

// Prepend each word to the beginning of the
// new sentence to reverse the word order.
reversed := From(words).AggregateT(
	func(workingSentence string, next string) string { return next + " " + workingSentence },
)

fmt.Println(reversed)
Output:

dog lazy the over jumps fox brown quick the

func (Query) AggregateWithSeed

func (q Query) AggregateWithSeed(seed interface{},
	f func(interface{}, interface{}) interface{}) interface{}

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

Aggregate method makes it simple to perform a calculation over a sequence of values. This method works by calling f() one time for each element in source except the first one. Each time f() is called, Aggregate passes both the element from the sequence and an aggregated value (as the first argument to f()). The value of the seed parameter is used as the initial aggregate value. The result of f() replaces the previous aggregated value.

Aggregate returns the final result of f().

Example

The following code example demonstrates how to use AggregateWithSeed function

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 := From(ints).
	AggregateWithSeed(0,
		func(total, next interface{}) interface{} {
			if next.(int)%2 == 0 {
				return total.(int) + 1
			}
			return total
		},
	)

fmt.Printf("The number of even integers is: %d", numEven)
Output:

The number of even integers is: 6

func (Query) AggregateWithSeedBy

func (q Query) AggregateWithSeedBy(seed interface{},
	f func(interface{}, interface{}) interface{},
	resultSelector func(interface{}) interface{}) interface{}

AggregateWithSeedBy 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.

Aggregate method makes it simple to perform a calculation over a sequence of values. This method works by calling f() one time for each element in source. Each time func is called, Aggregate passes both the element from the sequence and an aggregated value (as the first argument to func). The value of the seed parameter is used as the initial aggregate value. The result of func replaces the previous aggregated value.

The final result of func is passed to resultSelector to obtain the final result of Aggregate.

Example

The following code example demonstrates how to use AggregateWithSeedBy function

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

// Determine whether any string in the array is longer than "banana".
longestName := From(input).
	AggregateWithSeedBy("banana",
		func(longest interface{}, next interface{}) interface{} {
			if len(longest.(string)) > len(next.(string)) {
				return longest
			}
			return next

		},
		// Return the final result
		func(result interface{}) interface{} {
			return fmt.Sprintf("The fruit with the longest name is %s.", result)
		},
	)

fmt.Println(longestName)
Output:

The fruit with the longest name is passionfruit.

func (Query) AggregateWithSeedByT

func (q Query) AggregateWithSeedByT(seed interface{},
	f interface{},
	resultSelectorFn interface{}) interface{}

AggregateWithSeedByT is the typed version of AggregateWithSeedBy.

  • f is of type "func(TAccumulate, TSource) TAccumulate"
  • resultSelectorFn is of type "func(TAccumulate) TResult"

NOTE: AggregateWithSeedBy has better performance than AggregateWithSeedByT.

Example

The following code example demonstrates how to use AggregateWithSeedByT function

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

// Determine whether any string in the array is longer than "banana".
longestName := From(input).AggregateWithSeedByT("banana",
	func(longest string, next string) string {
		if len(longest) > len(next) {
			return longest
		}
		return next

	},
	// Return the final result
	func(result string) string {
		return fmt.Sprintf("The fruit with the longest name is %s.", result)
	},
)

fmt.Println(longestName)
Output:

The fruit with the longest name is passionfruit.

func (Query) AggregateWithSeedT

func (q Query) AggregateWithSeedT(seed interface{},
	f interface{}) interface{}

AggregateWithSeedT is the typed version of AggregateWithSeed.

  • f is of type "func(TAccumulate, TSource) TAccumulate"

NOTE: AggregateWithSeed has better performance than AggregateWithSeedT.

Example

The following code example demonstrates how to use AggregateWithSeed function

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

// Determine whether any string in the array is longer than "banana".
longestName := From(fruits).
	AggregateWithSeedT("banana",
		func(longest, next string) string {
			if len(next) > len(longest) {
				return next
			}
			return longest
		},
	)

fmt.Printf("The fruit with the longest name is %s.", longestName)
Output:

The fruit with the longest name is passionfruit.

func (Query) All

func (q Query) All(predicate func(interface{}) bool) bool

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

Example

The following code example demonstrates how to use All to determine whether all the elements in a slice satisfy a condition. Variable allStartWithB is true if all the pet names start with "B" or if the pets array is empty.

type Pet struct {
	Name string
	Age  int
}

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 := From(pets).
	All(
		func(pet interface{}) bool { return strings.HasPrefix(pet.(Pet).Name, "B") },
	)

fmt.Printf("All pet names start with 'B'? %t", allStartWithB)
Output:


 All pet names start with 'B'? false

func (Query) AllT

func (q Query) AllT(predicateFn interface{}) bool

AllT is the typed version of All.

  • predicateFn is of type "func(TSource) bool"

NOTE: All has better performance than AllT.

Example

The following code example demonstrates how to use AllT to get the students having all marks greater than 70.

type Student struct {
	Name  string
	Marks []int
}

students := []Student{
	{Name: "Hugo", Marks: []int{91, 88, 76, 93}},
	{Name: "Rick", Marks: []int{70, 73, 66, 90}},
	{Name: "Michael", Marks: []int{73, 80, 75, 88}},
	{Name: "Fadi", Marks: []int{82, 75, 66, 84}},
	{Name: "Peter", Marks: []int{67, 78, 70, 82}},
}

var approvedStudents []Student
From(students).
	WhereT(
		func(student Student) bool {
			return From(student.Marks).
				AllT(
					func(mark int) bool { return mark > 70 },
				)
		},
	).
	ToSlice(&approvedStudents)

//List of approved students
for _, student := range approvedStudents {
	fmt.Println(student.Name)
}
Output:

Hugo
Michael

func (Query) Any

func (q Query) Any() bool

Any determines whether any element of a collection exists.

Example

The following code example demonstrates how to use Any to determine whether a slice contains any elements.

numbers := []int{1, 2}
hasElements := From(numbers).Any()

fmt.Printf("Are there any element in the list? %t", hasElements)
Output:

Are there any element in the list? true

func (Query) AnyWith

func (q Query) AnyWith(predicate func(interface{}) bool) bool

AnyWith determines whether any element of a collection satisfies a condition.

Example

The following code example demonstrates how to use AnyWith to determine whether any element in a slice satisfies a condition.

type Pet struct {
	Name       string
	Age        int
	Vaccinated bool
}

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 := From(pets).
	AnyWith(
		func(p interface{}) bool {
			return p.(Pet).Age > 1 && p.(Pet).Vaccinated == false
		},
	)

fmt.Printf("Are there any unvaccinated animals over age one? %t", unvaccinated)
Output:


Are there any unvaccinated animals over age one? true

func (Query) AnyWithT

func (q Query) AnyWithT(predicateFn interface{}) bool

AnyWithT is the typed version of AnyWith.

  • predicateFn is of type "func(TSource) bool"

NOTE: AnyWith has better performance than AnyWithT.

Example

The following code example demonstrates how to use AnyWithT to get the students with any mark lower than 70.

type Student struct {
	Name  string
	Marks []int
}

students := []Student{
	{Name: "Hugo", Marks: []int{91, 88, 76, 93}},
	{Name: "Rick", Marks: []int{70, 73, 66, 90}},
	{Name: "Michael", Marks: []int{73, 80, 75, 88}},
	{Name: "Fadi", Marks: []int{82, 75, 66, 84}},
	{Name: "Peter", Marks: []int{67, 78, 70, 82}},
}

var studentsWithAnyMarkLt70 []Student
From(students).
	WhereT(
		func(student Student) bool {
			return From(student.Marks).
				AnyWithT(
					func(mark int) bool { return mark < 70 },
				)
		},
	).
	ToSlice(&studentsWithAnyMarkLt70)

//List of students with any mark lower than 70
for _, student := range studentsWithAnyMarkLt70 {
	fmt.Println(student.Name)
}
Output:

Rick
Fadi
Peter

func (Query) Append

func (q Query) Append(item interface{}) Query

Append inserts an item to the end of a collection, so it becomes the last item.

Example

The following code example demonstrates how to use Append to include an elements in the last position of a slice.

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

q := From(input).Append(5)

last := q.Last()

fmt.Println(last)
Output:

5

func (Query) Average

func (q Query) Average() (r float64)

Average computes the average of a collection of numeric values.

Example

The following code example demonstrates how to use Average to calculate the average of a slice of values.

grades := []int{78, 92, 100, 37, 81}
average := From(grades).Average()

fmt.Println(average)
Output:

77.6

func (Query) Concat

func (q Query) Concat(q2 Query) Query

Concat concatenates two collections.

The Concat method differs from the Union method because the Concat method returns all the original elements in the input sequences. The Union method returns only unique elements.

Example

The following code example demonstrates how to use Concat to concatenate two slices.

q := From([]int{1, 2, 3}).
	Concat(From([]int{4, 5, 6}))

fmt.Println(q.Results())
Output:

[1 2 3 4 5 6]

func (Query) Contains

func (q Query) Contains(value interface{}) bool

Contains determines whether a collection contains a specified element.

Example

The following code example demonstrates how to use Contains to determine whether a slice contains a specific element.

slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

has5 := From(slice).Contains(5)

fmt.Printf("Does the slice contains 5? %t", has5)
Output:

Does the slice contains 5? true

func (Query) Count

func (q Query) Count() (r int)

Count returns the number of elements in a collection.

Example

The following code example demonstrates how to use Count to count the elements in an array.

fruits := []string{"apple", "banana", "mango", "orange", "passionfruit", "grape"}
numberOfFruits := From(fruits).Count()

fmt.Println(numberOfFruits)
Output:

6

func (Query) CountWith

func (q Query) CountWith(predicate func(interface{}) bool) (r int)

CountWith returns a number that represents how many elements in the specified collection satisfy a condition.

Example

The following code example demonstrates how to use CountWith to count the even numbers in an array.

slice := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}

evenCount := From(slice).
	CountWith(
		func(item interface{}) bool { return item.(int)%2 == 0 },
	)

fmt.Println(evenCount)
Output:

6

func (Query) CountWithT

func (q Query) CountWithT(predicateFn interface{}) int

CountWithT is the typed version of CountWith.

  • predicateFn is of type "func(TSource) bool"

NOTE: CountWith has better performance than CountWithT.

Example

The following code example demonstrates how to use CountWithT to count the elements in an slice that satisfy a condition.

type Pet struct {
	Name       string
	Vaccinated bool
}

pets := []Pet{
	{Name: "Barley", Vaccinated: true},
	{Name: "Boots", Vaccinated: false},
	{Name: "Whiskers", Vaccinated: false},
}

numberUnvaccinated := From(pets).
	CountWithT(
		func(p Pet) bool { return p.Vaccinated == false },
	)

fmt.Printf("There are %d unvaccinated animals.", numberUnvaccinated)
Output:

There are 2 unvaccinated animals.

func (Query) Distinct

func (q Query) Distinct() Query

Distinct method returns distinct elements from a collection. The result is an unordered collection that contains no duplicate values.

Example

The following code example demonstrates how to use Distinct to return distinct elements from a slice of integers.

ages := []int{21, 46, 46, 55, 17, 21, 55, 55}

var distinctAges []int
From(ages).
	Distinct().
	ToSlice(&distinctAges)

fmt.Println(distinctAges)
Output:

[21 46 55 17]

func (Query) DistinctBy

func (q Query) DistinctBy(selector func(interface{}) interface{}) Query

DistinctBy method returns distinct elements from a collection. This method executes selector function for each element to determine a value to compare. The result is an unordered collection that contains no duplicate values.

Example

The following code example demonstrates how to use DistinctBy to return distinct elements from a ordered slice of elements.

type Product struct {
	Name string
	Code int
}

products := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

//Order and exclude duplicates.
var noduplicates []Product
From(products).
	DistinctBy(
		func(item interface{}) interface{} { return item.(Product).Code },
	).
	ToSlice(&noduplicates)

for _, product := range noduplicates {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

orange 4
apple 9
lemon 12

func (Query) DistinctByT

func (q Query) DistinctByT(selectorFn interface{}) Query

DistinctByT is the typed version of DistinctBy.

  • selectorFn is of type "func(TSource) TSource".

NOTE: DistinctBy has better performance than DistinctByT.

Example

The following code example demonstrates how to use DistinctByT to return distinct elements from a slice of structs.

type Product struct {
	Name string
	Code int
}

products := []Product{
	{Name: "apple", Code: 9},
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
}

//Exclude duplicates.
var noduplicates []Product
From(products).
	DistinctByT(
		func(item Product) int { return item.Code },
	).
	ToSlice(&noduplicates)

for _, product := range noduplicates {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

apple 9
orange 4
lemon 12

func (Query) Except

func (q Query) Except(q2 Query) Query

Except produces the set difference of two sequences. The set difference is the members of the first sequence that don't appear in the second sequence.

Example

The following code example demonstrates how to use the Except method to compare two slices of numbers and return elements that appear only in the first slice.

numbers1 := []float32{2.0, 2.1, 2.2, 2.3, 2.4, 2.5}
numbers2 := []float32{2.2}

var onlyInFirstSet []float32
From(numbers1).
	Except(From(numbers2)).
	ToSlice(&onlyInFirstSet)

for _, number := range onlyInFirstSet {
	fmt.Println(number)
}
Output:

2
2.1
2.3
2.4
2.5

func (Query) ExceptBy

func (q Query) ExceptBy(q2 Query,
	selector func(interface{}) interface{}) Query

ExceptBy invokes a transform function on each element of a collection and produces the set difference of two sequences. The set difference is the members of the first sequence that don't appear in the second sequence.

Example

The following code example demonstrates how to use the Except method to compare two slices of numbers and return elements that appear only in the first slice.

type Product struct {
	Name string
	Code int
}

fruits1 := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

fruits2 := []Product{
	{Name: "apple", Code: 9},
}

//Order and exclude duplicates.
var except []Product
From(fruits1).
	ExceptBy(From(fruits2),
		func(item interface{}) interface{} { return item.(Product).Code },
	).
	ToSlice(&except)

for _, product := range except {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

orange 4
lemon 12

func (Query) ExceptByT

func (q Query) ExceptByT(q2 Query,
	selectorFn interface{}) Query

ExceptByT is the typed version of ExceptBy.

  • selectorFn is of type "func(TSource) TSource"

NOTE: ExceptBy has better performance than ExceptByT.

Example

The following code example demonstrates how to use ExceptByT

type Product struct {
	Name string
	Code int
}

fruits1 := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

fruits2 := []Product{
	{Name: "apple", Code: 9},
}

//Order and exclude duplicates.
var except []Product
From(fruits1).
	ExceptByT(From(fruits2),
		func(item Product) int { return item.Code },
	).
	ToSlice(&except)

for _, product := range except {
	fmt.Printf("%s %d\n", product.Name, product.Code)
}
Output:

orange 4
lemon 12

func (Query) First

func (q Query) First() interface{}

First returns the first element of a collection.

Example

The following code example demonstrates how to use First to return the first element of an array.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19}

first := From(numbers).First()

fmt.Println(first)
Output:

9

func (Query) FirstWith

func (q Query) FirstWith(predicate func(interface{}) bool) interface{}

FirstWith returns the first element of a collection that satisfies a specified condition.

Example

The following code example demonstrates how to use FirstWith to return the first element of an array that satisfies a condition.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19}

first := From(numbers).
	FirstWith(
		func(item interface{}) bool { return item.(int) > 80 },
	)

fmt.Println(first)
Output:

92

func (Query) FirstWithT

func (q Query) FirstWithT(predicateFn interface{}) interface{}

FirstWithT is the typed version of FirstWith.

  • predicateFn is of type "func(TSource) bool"

NOTE: FirstWith has better performance than FirstWithT.

Example

The following code example demonstrates how to use FirstWithT to return the first element of an array that satisfies a condition.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54, 83, 23, 87, 435, 67, 12, 19}

first := From(numbers).
	FirstWithT(
		func(item int) bool { return item > 80 },
	)

fmt.Println(first)
Output:

92

func (Query) ForEach

func (q Query) ForEach(action func(interface{}))

ForEach performs the specified action on each element of a collection.

Example

The following code example demonstrates how to use ForEach to output all elements of an array.

fruits := []string{"orange", "apple", "lemon", "apple"}

From(fruits).ForEach(func(fruit interface{}) {
	fmt.Println(fruit)
})
Output:

orange
apple
lemon
apple

func (Query) ForEachIndexed

func (q Query) ForEachIndexed(action func(int, interface{}))

ForEachIndexed performs the specified action on each element of a collection.

The first argument to action represents the zero-based index of that element in the source collection. This can be useful if the elements are in a known order and you want to do something with an element at a particular index, for example. It can also be useful if you want to retrieve the index of one or more elements. The second argument to action represents the element to process.

Example

The following code example demonstrates how to use ForEachIndexed to output all elements of an array with its index.

fruits := []string{"orange", "apple", "lemon", "apple"}

From(fruits).ForEachIndexed(func(i int, fruit interface{}) {
	fmt.Printf("%d.%s\n", i, fruit)
})
Output:

0.orange
1.apple
2.lemon
3.apple

func (Query) ForEachIndexedT

func (q Query) ForEachIndexedT(actionFn interface{})

ForEachIndexedT is the typed version of ForEachIndexed.

  • actionFn is of type "func(int, TSource)"

NOTE: ForEachIndexed has better performance than ForEachIndexedT.

Example

The following code example demonstrates how to use ForEachIndexedT to output all elements of an array with its index.

fruits := []string{"orange", "apple", "lemon", "apple"}

From(fruits).ForEachIndexedT(func(i int, fruit string) {
	fmt.Printf("%d.%s\n", i, fruit)
})
Output:

0.orange
1.apple
2.lemon
3.apple

func (Query) ForEachT

func (q Query) ForEachT(actionFn interface{})

ForEachT is the typed version of ForEach.

  • actionFn is of type "func(TSource)"

NOTE: ForEach has better performance than ForEachT.

Example

The following code example demonstrates how to use ForEachT to output all elements of an array.

fruits := []string{"orange", "apple", "lemon", "apple"}

From(fruits).ForEachT(func(fruit string) {
	fmt.Println(fruit)
})
Output:

orange
apple
lemon
apple

func (Query) GroupBy

func (q Query) GroupBy(keySelector func(interface{}) interface{},
	elementSelector func(interface{}) interface{}) Query

GroupBy method groups the elements of a collection according to a specified key selector function and projects the elements for each group by using a specified function.

Example
input := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}

q := From(input).GroupBy(
	func(i interface{}) interface{} { return i.(int) % 2 },
	func(i interface{}) interface{} { return i.(int) })

fmt.Println(q.OrderBy(func(i interface{}) interface{} {
	return i.(Group).Key
}).Results())
Output:

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

func (Query) GroupByT

func (q Query) GroupByT(keySelectorFn interface{},
	elementSelectorFn interface{}) Query

GroupByT is the typed version of GroupBy.

  • keySelectorFn is of type "func(TSource) TKey"
  • elementSelectorFn is of type "func(TSource) TElement"

NOTE: GroupBy has better performance than GroupByT.

Example

The following code example demonstrates how to use GroupByT to group the elements of a slice.

type Pet struct {
	Name string
	Age  int
}
// Create a list of pets.
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.
var query []Group
From(pets).GroupByT(
	func(p Pet) int { return p.Age },
	func(p Pet) string { return p.Name },
).OrderByT(
	func(g Group) int { return g.Key.(int) },
).ToSlice(&query)

for _, petGroup := range query {
	fmt.Printf("%d\n", petGroup.Key)
	for _, petName := range petGroup.Group {
		fmt.Printf("  %s\n", petName)
	}

}
Output:

1
  Whiskers
4
  Boots
  Daisy
8
  Barley

func (Query) GroupJoin

func (q Query) GroupJoin(inner Query,
	outerKeySelector func(interface{}) interface{},
	innerKeySelector func(interface{}) interface{},
	resultSelector func(outer interface{}, inners []interface{}) interface{}) Query

GroupJoin correlates the elements of two collections based on key equality, and groups the results.

This method produces hierarchical results, which means that elements from outer query are paired with collections of matching elements from inner. GroupJoin enables you to base your results on a whole set of matches for each element of outer query.

The resultSelector function is called only one time for each outer element together with a collection of all the inner elements that match the outer element. This differs from the Join method, in which the result selector function is invoked on pairs that contain one element from outer and one element from inner.

GroupJoin preserves the order of the elements of outer, and for each element of outer, the order of the matching elements from inner.

Example

The following code example demonstrates how to use GroupJoin to perform a grouped join on two slices

fruits := []string{
	"apple",
	"banana",
	"apricot",
	"cherry",
	"clementine",
}

q := FromString("abc").
	GroupJoin(From(fruits),
		func(i interface{}) interface{} { return i },
		func(i interface{}) interface{} { return []rune(i.(string))[0] },
		func(outer interface{}, inners []interface{}) interface{} {
			return KeyValue{string(outer.(rune)), inners}
		},
	)

fmt.Println(q.Results())
Output:

[{a [apple apricot]} {b [banana]} {c [cherry clementine]}]

func (Query) GroupJoinT

func (q Query) GroupJoinT(inner Query,
	outerKeySelectorFn interface{},
	innerKeySelectorFn interface{},
	resultSelectorFn interface{}) Query

GroupJoinT is the typed version of GroupJoin.

  • inner: The query to join to the outer query.
  • outerKeySelectorFn is of type "func(TOuter) TKey"
  • innerKeySelectorFn is of type "func(TInner) TKey"
  • resultSelectorFn: is of type "func(TOuter, inners []TInner) TResult"

NOTE: GroupJoin has better performance than GroupJoinT.

Example

The following code example demonstrates how to use GroupJoinT

to perform a grouped join on two slices.
type Person struct {
	Name string
}

type Pet struct {
	Name  string
	Owner Person
}

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}

people := []Person{magnus, terry, charlotte}
pets := []Pet{barley, boots, whiskers, daisy}

// Create a slice where each element is a KeyValue
// that contains a person's name as the key and a slice of strings
// of names of the pets they own as a value.

q := []KeyValue{}
From(people).
	GroupJoinT(From(pets),
		func(p Person) Person { return p },
		func(p Pet) Person { return p.Owner },
		func(person Person, pets []Pet) KeyValue {
			var petNames []string
			From(pets).
				SelectT(
					func(pet Pet) string { return pet.Name },
				).
				ToSlice(&petNames)
			return KeyValue{person.Name, petNames}
		},
	).ToSlice(&q)

for _, obj := range q {
	// Output the owner's name.
	fmt.Printf("%s:\n", obj.Key)
	// Output each of the owner's pet's names.
	for _, petName := range obj.Value.([]string) {
		fmt.Printf("  %s\n", petName)
	}
}
Output:

Hedlund, Magnus:
  Daisy
Adams, Terry:
  Barley
  Boots
Weiss, Charlotte:
  Whiskers

func (Query) Intersect

func (q Query) Intersect(q2 Query) Query

Intersect produces the set intersection of the source collection and the provided input collection. The intersection of two sets A and B is defined as the set that contains all the elements of A that also appear in B, but no other elements.

Example

The following code example demonstrates how to use Intersect to return the elements that appear in each of two slices of integers.

id1 := []int{44, 26, 92, 30, 71, 38}
id2 := []int{39, 59, 83, 47, 26, 4, 30}

var both []int
From(id1).
	Intersect(From(id2)).
	ToSlice(&both)

for _, id := range both {
	fmt.Println(id)
}
Output:

26
30

func (Query) IntersectBy

func (q Query) IntersectBy(q2 Query,
	selector func(interface{}) interface{}) Query

IntersectBy produces the set intersection of the source collection and the provided input collection. The intersection of two sets A and B is defined as the set that contains all the elements of A that also appear in B, but no other elements.

IntersectBy invokes a transform function on each element of both collections.

Example

The following code example demonstrates how to use IntersectBy to return the elements that appear in each of two slices of products with same Code.

type Product struct {
	Name string
	Code int
}

store1 := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
}

store2 := []Product{
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

var duplicates []Product
From(store1).
	IntersectBy(From(store2),
		func(p interface{}) interface{} { return p.(Product).Code },
	).
	ToSlice(&duplicates)

for _, p := range duplicates {
	fmt.Println(p.Name, "", p.Code)
}
Output:

apple  9

func (Query) IntersectByT

func (q Query) IntersectByT(q2 Query,
	selectorFn interface{}) Query

IntersectByT is the typed version of IntersectBy.

  • selectorFn is of type "func(TSource) TSource"

NOTE: IntersectBy has better performance than IntersectByT.

Example

The following code example demonstrates how to use IntersectByT to return the elements that appear in each of two slices of products with same Code.

type Product struct {
	Name string
	Code int
}

store1 := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
}

store2 := []Product{
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

var duplicates []Product
From(store1).
	IntersectByT(From(store2),
		func(p Product) int { return p.Code },
	).
	ToSlice(&duplicates)

for _, p := range duplicates {
	fmt.Println(p.Name, "", p.Code)
}
Output:

apple  9

func (Query) Join

func (q Query) Join(inner Query,
	outerKeySelector func(interface{}) interface{},
	innerKeySelector func(interface{}) interface{},
	resultSelector func(outer interface{}, inner interface{}) interface{}) Query

Join correlates the elements of two collection based on matching keys.

A join refers to the operation of correlating the elements of two sources of information based on a common key. Join brings the two information sources and the keys by which they are matched together in one method call. This differs from the use of SelectMany, which requires more than one method call to perform the same operation.

Join preserves the order of the elements of outer collection, and for each of these elements, the order of the matching elements of inner.

Example

The following code example demonstrates how to use Join to perform an inner join of two slices based on a common key.

fruits := []string{
	"apple",
	"banana",
	"apricot",
	"cherry",
	"clementine",
}

q := Range(1, 10).
	Join(From(fruits),
		func(i interface{}) interface{} { return i },
		func(i interface{}) interface{} { return len(i.(string)) },
		func(outer interface{}, inner interface{}) interface{} {
			return KeyValue{outer, inner}
		},
	)

fmt.Println(q.Results())
Output:

[{5 apple} {6 banana} {6 cherry} {7 apricot} {10 clementine}]

func (Query) JoinT

func (q Query) JoinT(inner Query,
	outerKeySelectorFn interface{},
	innerKeySelectorFn interface{},
	resultSelectorFn interface{}) Query

JoinT is the typed version of Join.

  • outerKeySelectorFn is of type "func(TOuter) TKey"
  • innerKeySelectorFn is of type "func(TInner) TKey"
  • resultSelectorFn is of type "func(TOuter,TInner) TResult"

NOTE: Join has better performance than JoinT.

Example

The following code example demonstrates how to use JoinT to perform an inner join of two slices based on a common key.

type Person struct {
	Name string
}

type Pet struct {
	Name  string
	Owner Person
}

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}

people := []Person{magnus, terry, charlotte}
pets := []Pet{barley, boots, whiskers, daisy}

// Create a list of Person-Pet pairs where
// each element is an anonymous type that contains a
// Pet's name and the name of the Person that owns the Pet.

query := []string{}
From(people).
	JoinT(From(pets),
		func(person Person) Person { return person },
		func(pet Pet) Person { return pet.Owner },
		func(person Person, pet Pet) string { return fmt.Sprintf("%s - %s", person.Name, pet.Name) },
	).ToSlice(&query)

for _, line := range query {
	fmt.Println(line)
}
Output:

Hedlund, Magnus - Daisy
Adams, Terry - Barley
Adams, Terry - Boots
Weiss, Charlotte - Whiskers

func (Query) Last

func (q Query) Last() (r interface{})

Last returns the last element of a collection.

Example

The following code example demonstrates how to use Last to return the last element of an array.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54,
	83, 23, 87, 67, 12, 19}

last := From(numbers).Last()

fmt.Println(last)
Output:

19

func (Query) LastWith

func (q Query) LastWith(predicate func(interface{}) bool) (r interface{})

LastWith returns the last element of a collection that satisfies a specified condition.

Example

The following code example demonstrates how to use LastWith to return the last element of an array.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54,
	83, 23, 87, 67, 12, 19}

last := From(numbers).
	LastWith(
		func(n interface{}) bool { return n.(int) > 80 },
	)

fmt.Println(last)
Output:

87

func (Query) LastWithT

func (q Query) LastWithT(predicateFn interface{}) interface{}

LastWithT is the typed version of LastWith.

  • predicateFn is of type "func(TSource) bool"

NOTE: LastWith has better performance than LastWithT.

Example

The following code example demonstrates how to use LastWithT to return the last element of an array.

numbers := []int{9, 34, 65, 92, 87, 435, 3, 54,
	83, 23, 87, 67, 12, 19}

last := From(numbers).
	LastWithT(
		func(n int) bool { return n > 80 },
	)

fmt.Println(last)
Output:

87

func (Query) Max

func (q Query) Max() (r interface{})

Max returns the maximum value in a collection of values.

Example

The following code example demonstrates how to use Max to determine the maximum value in a slice.

numbers := []int64{4294967296, 466855135, 81125}

last := From(numbers).Max()

fmt.Println(last)
Output:

4294967296

func (Query) Min

func (q Query) Min() (r interface{})

Min returns the minimum value in a collection of values.

Example

The following code example demonstrates how to use Min to determine the minimum value in a slice.

grades := []int{78, 92, 99, 37, 81}

min := From(grades).Min()

fmt.Println(min)
Output:

37

func (Query) OrderBy

func (q Query) OrderBy(selector func(interface{}) interface{}) OrderedQuery

OrderBy sorts the elements of a collection in ascending order. Elements are sorted according to a key.

Example

The following code example demonstrates how to use OrderBy to sort the elements of a slice.

q := Range(1, 10).
	OrderBy(
		func(i interface{}) interface{} { return i.(int) % 2 },
	).
	ThenByDescending(
		func(i interface{}) interface{} { return i },
	)

fmt.Println(q.Results())
Output:

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

func (Query) OrderByDescending

func (q Query) OrderByDescending(selector func(interface{}) interface{}) OrderedQuery

OrderByDescending sorts the elements of a collection in descending order. Elements are sorted according to a key.

Example

The following code example demonstrates how to use OrderByDescending to sort the elements of a slice in descending order by using a selector function

names := []string{"Ned", "Ben", "Susan"}

var result []string
From(names).
	OrderByDescending(
		func(n interface{}) interface{} { return n },
	).ToSlice(&result)

fmt.Println(result)
Output:

[Susan Ned Ben]

func (Query) OrderByDescendingT

func (q Query) OrderByDescendingT(selectorFn interface{}) OrderedQuery

OrderByDescendingT is the typed version of OrderByDescending.

  • selectorFn is of type "func(TSource) TKey"

NOTE: OrderByDescending has better performance than OrderByDescendingT.

Example

The following code example demonstrates how to use OrderByDescendingT to order an slice.

type Player struct {
	Name   string
	Points int64
}

players := []Player{
	{Name: "Hugo", Points: 4757},
	{Name: "Rick", Points: 7365},
	{Name: "Michael", Points: 2857},
	{Name: "Fadi", Points: 85897},
	{Name: "Peter", Points: 48576},
}

//Order and get the top 3 players
var top3Players []KeyValue
From(players).
	OrderByDescendingT(
		func(p Player) int64 { return p.Points },
	).
	Take(3).
	SelectIndexedT(
		func(i int, p Player) KeyValue { return KeyValue{Key: i + 1, Value: p} },
	).
	ToSlice(&top3Players)

for _, rank := range top3Players {
	fmt.Printf(
		"Rank: #%d - Player: %s - Points: %d\n",
		rank.Key,
		rank.Value.(Player).Name,
		rank.Value.(Player).Points,
	)

}
Output:

Rank: #1 - Player: Fadi - Points: 85897
Rank: #2 - Player: Peter - Points: 48576
Rank: #3 - Player: Rick - Points: 7365

func (Query) OrderByT

func (q Query) OrderByT(selectorFn interface{}) OrderedQuery

OrderByT is the typed version of OrderBy.

  • selectorFn is of type "func(TSource) TKey"

NOTE: OrderBy has better performance than OrderByT.

Example

The following code example demonstrates how to use OrderByT to sort the elements of a slice.

type Pet struct {
	Name string
	Age  int
}
// Create a list of pets.
pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
	{Name: "Daisy", Age: 4},
}

var orderedPets []Pet
From(pets).
	OrderByT(
		func(pet Pet) int { return pet.Age },
	).
	ToSlice(&orderedPets)

for _, pet := range orderedPets {
	fmt.Println(pet.Name, "-", pet.Age)
}
Output:

Whiskers - 1
Boots - 4
Daisy - 4
Barley - 8

func (Query) Prepend

func (q Query) Prepend(item interface{}) Query

Prepend inserts an item to the beginning of a collection, so it becomes the first item.

Example

The following code example demonstrates how to use Prepend to include an elements in the first position of a slice.

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

q := From(input).Prepend(1)
first := q.First()

fmt.Println(first)
Output:

1

func (Query) Results

func (q Query) Results() (r []interface{})

Results iterates over a collection and returnes slice of interfaces

func (Query) Reverse

func (q Query) Reverse() Query

Reverse inverts the order of the elements in a collection.

Unlike OrderBy, this sorting method does not consider the actual values themselves in determining the order. Rather, it just returns the elements in the reverse order from which they are produced by the underlying source.

Example

The following code example demonstrates how to use Reverse to reverse the order of elements in a string.

input := "apple"

var output []rune
From(input).
	Reverse().
	ToSlice(&output)

fmt.Println(string(output))
Output:

elppa

func (Query) Select

func (q Query) Select(selector func(interface{}) interface{}) Query

Select projects each element of a collection into a new form. Returns a query with the result of invoking the transform function on each element of original source.

This projection method requires the transform function, selector, to produce one value for each value in the source collection. If selector returns a value that is itself a collection, it is up to the consumer to traverse the subcollections manually. In such a situation, it might be better for your query to return a single coalesced collection of values. To achieve this, use the SelectMany method instead of Select. Although SelectMany works similarly to Select, it differs in that the transform function returns a collection that is then expanded by SelectMany before it is returned.

Example

The following code example demonstrates how to use Select to project over a slice of values.

squares := []int{}

Range(1, 10).
	Select(
		func(x interface{}) interface{} { return x.(int) * x.(int) },
	).
	ToSlice(&squares)

fmt.Println(squares)
Output:

[1 4 9 16 25 36 49 64 81 100]

func (Query) SelectIndexed

func (q Query) SelectIndexed(selector func(int, interface{}) interface{}) Query

SelectIndexed projects each element of a collection into a new form by incorporating the element's index. Returns a query with the result of invoking the transform function on each element of original source.

The first argument to selector represents the zero-based index of that element in the source collection. This can be useful if the elements are in a known order and you want to do something with an element at a particular index, for example. It can also be useful if you want to retrieve the index of one or more elements. The second argument to selector represents the element to process.

This projection method requires the transform function, selector, to produce one value for each value in the source collection. If selector returns a value that is itself a collection, it is up to the consumer to traverse the subcollections manually. In such a situation, it might be better for your query to return a single coalesced collection of values. To achieve this, use the SelectMany method instead of Select. Although SelectMany works similarly to Select, it differs in that the transform function returns a collection that is then expanded by SelectMany before it is returned.

Example

The following code example demonstrates how to use Select to project over a slice of values and use the index of each element.

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

result := []string{}
From(fruits).
	SelectIndexed(
		func(index int, fruit interface{}) interface{} { return fruit.(string)[:index] },
	).
	ToSlice(&result)

fmt.Println(result)
Output:

[ b ma ora pass grape]

func (Query) SelectIndexedT

func (q Query) SelectIndexedT(selectorFn interface{}) Query

SelectIndexedT is the typed version of SelectIndexed.

  • selectorFn is of type "func(int,TSource)TResult"

NOTE: SelectIndexed has better performance than SelectIndexedT.

Example

The following code example demonstrates how to use SelectIndexedT to determine if the value in a slice of int match their position in the slice.

numbers := []int{5, 4, 1, 3, 9, 8, 6, 7, 2, 0}

var numsInPlace []KeyValue

From(numbers).
	SelectIndexedT(
		func(index, num int) KeyValue { return KeyValue{Key: num, Value: (num == index)} },
	).
	ToSlice(&numsInPlace)

fmt.Println("Number: In-place?")
for _, n := range numsInPlace {
	fmt.Printf("%d: %t\n", n.Key, n.Value)
}
Output:

Number: In-place?
5: false
4: false
1: false
3: true
9: false
8: false
6: true
7: true
2: false
0: false

func (Query) SelectMany

func (q Query) SelectMany(selector func(interface{}) Query) Query

SelectMany projects each element of a collection to a Query, iterates and flattens the resulting collection into one collection.

Example
input := [][]int{{1, 2, 3}, {4, 5, 6, 7}}

q := From(input).
	SelectMany(
		func(i interface{}) Query { return From(i) },
	)

fmt.Println(q.Results())
Output:

[1 2 3 4 5 6 7]

func (Query) SelectManyBy

func (q Query) SelectManyBy(selector func(interface{}) Query,
	resultSelector func(interface{}, interface{}) interface{}) Query

SelectManyBy projects each element of a collection to a Query, iterates and flattens the resulting collection into one collection, and invokes a result selector function on each element therein.

Example

The following code example demonstrates how to use SelectMany to perform a one-to-many projection over a slice

type Pet struct {
	Name string
}

type Person struct {
	Name string
	Pets []Pet
}

magnus := Person{
	Name: "Hedlund, Magnus",
	Pets: []Pet{{Name: "Daisy"}},
}

terry := Person{
	Name: "Adams, Terry",
	Pets: []Pet{{Name: "Barley"}, {Name: "Boots"}},
}
charlotte := Person{
	Name: "Weiss, Charlotte",
	Pets: []Pet{{Name: "Whiskers"}},
}

people := []Person{magnus, terry, charlotte}
var results []string
From(people).
	SelectManyBy(
		func(person interface{}) Query { return From(person.(Person).Pets) },
		func(pet, person interface{}) interface{} {
			return fmt.Sprintf("Owner: %s, Pet: %s", person.(Person).Name, pet.(Pet).Name)
		},
	).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

Owner: Hedlund, Magnus, Pet: Daisy
Owner: Adams, Terry, Pet: Barley
Owner: Adams, Terry, Pet: Boots
Owner: Weiss, Charlotte, Pet: Whiskers

func (Query) SelectManyByIndexed

func (q Query) SelectManyByIndexed(selector func(int, interface{}) Query,
	resultSelector func(interface{}, interface{}) interface{}) Query

SelectManyByIndexed projects each element of a collection to a Query, iterates and flattens the resulting collection into one collection, and invokes a result selector function on each element therein. The index of each source element is used in the intermediate projected form of that element.

Example

The following code example demonstrates how to use SelectManyByIndexed to perform a one-to-many projection over an array and use the index of each outer element.

type Pet struct {
	Name string
}

type Person struct {
	Name string
	Pets []Pet
}

magnus := Person{
	Name: "Hedlund, Magnus",
	Pets: []Pet{{Name: "Daisy"}},
}

terry := Person{
	Name: "Adams, Terry",
	Pets: []Pet{{Name: "Barley"}, {Name: "Boots"}},
}
charlotte := Person{
	Name: "Weiss, Charlotte",
	Pets: []Pet{{Name: "Whiskers"}},
}

people := []Person{magnus, terry, charlotte}
var results []string

From(people).
	SelectManyByIndexed(
		func(index int, person interface{}) Query {
			return From(person.(Person).Pets).
				Select(func(pet interface{}) interface{} {
					return fmt.Sprintf("%d - %s", index, pet.(Pet).Name)
				})
		},
		func(indexedPet, person interface{}) interface{} {
			return fmt.Sprintf("Pet: %s, Owner: %s", indexedPet, person.(Person).Name)
		},
	).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

Pet: 0 - Daisy, Owner: Hedlund, Magnus
Pet: 1 - Barley, Owner: Adams, Terry
Pet: 1 - Boots, Owner: Adams, Terry
Pet: 2 - Whiskers, Owner: Weiss, Charlotte

func (Query) SelectManyByIndexedT

func (q Query) SelectManyByIndexedT(selectorFn interface{},
	resultSelectorFn interface{}) Query

SelectManyByIndexedT is the typed version of SelectManyByIndexed.

  • selectorFn is of type "func(int,TSource)Query"
  • resultSelectorFn is of type "func(TSource,TCollection)TResult"

NOTE: SelectManyByIndexed has better performance than SelectManyByIndexedT.

Example

The following code example demonstrates how to use SelectManyByIndexedT to perform a one-to-many projection over an array and use the index of each outer element.

type Pet struct {
	Name string
}

type Person struct {
	Name string
	Pets []Pet
}

magnus := Person{
	Name: "Hedlund, Magnus",
	Pets: []Pet{{Name: "Daisy"}},
}

terry := Person{
	Name: "Adams, Terry",
	Pets: []Pet{{Name: "Barley"}, {Name: "Boots"}},
}
charlotte := Person{
	Name: "Weiss, Charlotte",
	Pets: []Pet{{Name: "Whiskers"}},
}

people := []Person{magnus, terry, charlotte}
var results []string

From(people).
	SelectManyByIndexedT(
		func(index int, person Person) Query {
			return From(person.Pets).
				SelectT(func(pet Pet) string {
					return fmt.Sprintf("%d - %s", index, pet.Name)
				})
		},
		func(indexedPet string, person Person) string {
			return fmt.Sprintf("Pet: %s, Owner: %s", indexedPet, person.Name)
		},
	).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

Pet: 0 - Daisy, Owner: Hedlund, Magnus
Pet: 1 - Barley, Owner: Adams, Terry
Pet: 1 - Boots, Owner: Adams, Terry
Pet: 2 - Whiskers, Owner: Weiss, Charlotte

func (Query) SelectManyByT

func (q Query) SelectManyByT(selectorFn interface{},
	resultSelectorFn interface{}) Query

SelectManyByT is the typed version of SelectManyBy.

  • selectorFn is of type "func(TSource)Query"
  • resultSelectorFn is of type "func(TSource,TCollection)TResult"

NOTE: SelectManyBy has better performance than SelectManyByT.

Example

The following code example demonstrates how to use SelectManyT to perform a one-to-many projection over a slice

type Pet struct {
	Name string
}

type Person struct {
	Name string
	Pets []Pet
}

magnus := Person{
	Name: "Hedlund, Magnus",
	Pets: []Pet{{Name: "Daisy"}},
}

terry := Person{
	Name: "Adams, Terry",
	Pets: []Pet{{Name: "Barley"}, {Name: "Boots"}},
}
charlotte := Person{
	Name: "Weiss, Charlotte",
	Pets: []Pet{{Name: "Whiskers"}},
}

people := []Person{magnus, terry, charlotte}
var results []string
From(people).
	SelectManyByT(
		func(person Person) Query { return From(person.Pets) },
		func(pet Pet, person Person) interface{} {
			return fmt.Sprintf("Owner: %s, Pet: %s", person.Name, pet.Name)
		},
	).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

Owner: Hedlund, Magnus, Pet: Daisy
Owner: Adams, Terry, Pet: Barley
Owner: Adams, Terry, Pet: Boots
Owner: Weiss, Charlotte, Pet: Whiskers

func (Query) SelectManyIndexed

func (q Query) SelectManyIndexed(selector func(int, interface{}) Query) Query

SelectManyIndexed projects each element of a collection to a Query, iterates and flattens the resulting collection into one collection.

The first argument to selector represents the zero-based index of that element in the source collection. This can be useful if the elements are in a known order and you want to do something with an element at a particular index, for example. It can also be useful if you want to retrieve the index of one or more elements. The second argument to selector represents the element to process.

Example

The following code example demonstrates how to use SelectManyIndexed to perform a one-to-many projection over an slice of log data and print out their contents.

type LogFile struct {
	Name  string
	Lines []string
}

file1 := LogFile{
	Name: "file1.log",
	Lines: []string{
		"INFO: 2013/11/05 18:11:01 main.go:44: Special Information",
		"WARNING: 2013/11/05 18:11:01 main.go:45: There is something you need to know about",
		"ERROR: 2013/11/05 18:11:01 main.go:46: Something has failed",
	},
}

file2 := LogFile{
	Name: "file2.log",
	Lines: []string{
		"INFO: 2013/11/05 18:11:01 main.go:46: Everything is ok",
	},
}

file3 := LogFile{
	Name: "file3.log",
	Lines: []string{
		"2013/11/05 18:42:26 Hello World",
	},
}

logFiles := []LogFile{file1, file2, file3}
var results []string

From(logFiles).
	SelectManyIndexedT(func(fileIndex int, file LogFile) Query {
		return From(file.Lines).
			SelectIndexedT(func(lineIndex int, line string) string {
				return fmt.Sprintf("File:[%d] - %s => line: %d - %s", fileIndex+1, file.Name, lineIndex+1, line)
			})
	}).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

File:[1] - file1.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:44: Special Information
File:[1] - file1.log => line: 2 - WARNING: 2013/11/05 18:11:01 main.go:45: There is something you need to know about
File:[1] - file1.log => line: 3 - ERROR: 2013/11/05 18:11:01 main.go:46: Something has failed
File:[2] - file2.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:46: Everything is ok
File:[3] - file3.log => line: 1 - 2013/11/05 18:42:26 Hello World

func (Query) SelectManyIndexedT

func (q Query) SelectManyIndexedT(selectorFn interface{}) Query

SelectManyIndexedT is the typed version of SelectManyIndexed.

  • selectorFn is of type "func(int,TSource)Query"

NOTE: SelectManyIndexed has better performance than SelectManyIndexedT.

Example

The following code example demonstrates how to use SelectManyIndexedT to perform a one-to-many projection over an slice of log files and print out their contents.

type LogFile struct {
	Name  string
	Lines []string
}

file1 := LogFile{
	Name: "file1.log",
	Lines: []string{
		"INFO: 2013/11/05 18:11:01 main.go:44: Special Information",
		"WARNING: 2013/11/05 18:11:01 main.go:45: There is something you need to know about",
		"ERROR: 2013/11/05 18:11:01 main.go:46: Something has failed",
	},
}

file2 := LogFile{
	Name: "file2.log",
	Lines: []string{
		"INFO: 2013/11/05 18:11:01 main.go:46: Everything is ok",
	},
}

file3 := LogFile{
	Name: "file3.log",
	Lines: []string{
		"2013/11/05 18:42:26 Hello World",
	},
}

logFiles := []LogFile{file1, file2, file3}
var results []string

From(logFiles).
	SelectManyIndexedT(func(fileIndex int, file LogFile) Query {
		return From(file.Lines).
			SelectIndexedT(func(lineIndex int, line string) string {
				return fmt.Sprintf("File:[%d] - %s => line: %d - %s", fileIndex+1, file.Name, lineIndex+1, line)
			})
	}).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

File:[1] - file1.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:44: Special Information
File:[1] - file1.log => line: 2 - WARNING: 2013/11/05 18:11:01 main.go:45: There is something you need to know about
File:[1] - file1.log => line: 3 - ERROR: 2013/11/05 18:11:01 main.go:46: Something has failed
File:[2] - file2.log => line: 1 - INFO: 2013/11/05 18:11:01 main.go:46: Everything is ok
File:[3] - file3.log => line: 1 - 2013/11/05 18:42:26 Hello World

func (Query) SelectManyT

func (q Query) SelectManyT(selectorFn interface{}) Query

SelectManyT is the typed version of SelectMany.

  • selectorFn is of type "func(TSource)Query"

NOTE: SelectMany has better performance than SelectManyT.

Example

The following code example demonstrates how to use SelectManyT to perform a projection over a list of sentences and rank the top 5 most used words

sentences := []string{
	"the quick brown fox jumps over the lazy dog",
	"pack my box with five dozen liquor jugs",
	"several fabulous dixieland jazz groups played with quick tempo",
	"back in my quaint garden jaunty zinnias vie with flaunting phlox",
	"five or six big jet planes zoomed quickly by the new tower",
	"I quickly explained that many big jobs involve few hazards",
	"The wizard quickly jinxed the gnomes before they vaporized",
}

var results []string
From(sentences).
	//Split the sentences in words
	SelectManyT(func(sentence string) Query {
		return From(strings.Split(sentence, " "))
	}).
	//Grouping by word
	GroupByT(
		func(word string) string { return word },
		func(word string) string { return word },
	).
	//Ordering by word counts
	OrderByDescendingT(func(wordGroup Group) int {
		return len(wordGroup.Group)
	}).
	//Then order by word
	ThenByT(func(wordGroup Group) string {
		return wordGroup.Key.(string)
	}).
	//Take the top 5
	Take(5).
	//Project the words using the index as rank
	SelectIndexedT(func(index int, wordGroup Group) string {
		return fmt.Sprintf("Rank: #%d, Word: %s, Counts: %d", index+1, wordGroup.Key, len(wordGroup.Group))
	}).
	ToSlice(&results)

for _, result := range results {
	fmt.Println(result)
}
Output:

Rank: #1, Word: the, Counts: 4
Rank: #2, Word: quickly, Counts: 3
Rank: #3, Word: with, Counts: 3
Rank: #4, Word: big, Counts: 2
Rank: #5, Word: five, Counts: 2

func (Query) SelectT

func (q Query) SelectT(selectorFn interface{}) Query

SelectT is the typed version of Select.

  • selectorFn is of type "func(TSource)TResult"

NOTE: Select has better performance than SelectT.

Example

The following code example demonstrates how to use SelectT to project over a slice.

squares := []int{}

Range(1, 10).
	SelectT(
		func(x int) int { return x * x },
	).
	ToSlice(&squares)

fmt.Println(squares)
Output:

[1 4 9 16 25 36 49 64 81 100]

func (Query) SequenceEqual

func (q Query) SequenceEqual(q2 Query) bool

SequenceEqual determines whether two collections are equal.

Example

The following code example demonstrates how to use SequenceEqual to determine whether two slices are equal.

type Pet struct {
	Name string
	Age  int
}

pets1 := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
	{Name: "Daisy", Age: 4},
}

pets2 := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
	{Name: "Daisy", Age: 4},
}

equal := From(pets1).SequenceEqual(From(pets2))

fmt.Printf("Are the lists equals? %t", equal)
Output:

Are the lists equals? true

func (Query) Single

func (q Query) Single() interface{}

Single returns the only element of a collection, and nil if there is not exactly one element in the collection.

Example

The following code example demonstrates how to use Single to select the only element of a slice.

fruits1 := []string{"orange"}

fruit1 := From(fruits1).Single()

fmt.Println(fruit1)
Output:

orange

func (Query) SingleWith

func (q Query) SingleWith(predicate func(interface{}) bool) (r interface{})

SingleWith returns the only element of a collection that satisfies a specified condition, and nil if more than one such element exists.

Example

The following code example demonstrates how to use SingleWith to select the only element of a slice that satisfies a condition.

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

fruit := From(fruits).
	SingleWith(
		func(f interface{}) bool { return len(f.(string)) > 10 },
	)

fmt.Println(fruit)
Output:

passionfruit

func (Query) SingleWithT

func (q Query) SingleWithT(predicateFn interface{}) interface{}

SingleWithT is the typed version of SingleWith.

  • predicateFn is of type "func(TSource) bool"

NOTE: SingleWith has better performance than SingleWithT.

Example

The following code example demonstrates how to use SingleWithT to select the only element of a slice that satisfies a condition.

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

fruit := From(fruits).
	SingleWithT(
		func(f string) bool { return len(f) > 10 },
	)

fmt.Println(fruit)
Output:

passionfruit

func (Query) Skip

func (q Query) Skip(count int) Query

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

Example

The following code example demonstrates how to use Skip to skip a specified number of elements in a sorted array and return the remaining elements.

grades := []int{59, 82, 70, 56, 92, 98, 85}
var lowerGrades []int
From(grades).
	OrderByDescending(
		func(g interface{}) interface{} { return g },
	).
	Skip(3).
	ToSlice(&lowerGrades)

//All grades except the top three are:
fmt.Println(lowerGrades)
Output:

[82 70 59 56]

func (Query) SkipWhile

func (q Query) SkipWhile(predicate func(interface{}) bool) Query

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

This method tests each element by using predicate and skips the element if the result is true. After the predicate function returns false for an element, that element and the remaining elements in source are returned and there are no more invocations of predicate.

Example

The following code example demonstrates how to use SkipWhile to skip elements of an array as long as a condition is true.

grades := []int{59, 82, 70, 56, 92, 98, 85}
var lowerGrades []int
From(grades).
	OrderByDescending(
		func(g interface{}) interface{} { return g },
	).
	SkipWhile(
		func(g interface{}) bool { return g.(int) >= 80 },
	).
	ToSlice(&lowerGrades)

// All grades below 80:
fmt.Println(lowerGrades)
Output:

[70 59 56]

func (Query) SkipWhileIndexed

func (q Query) SkipWhileIndexed(predicate func(int, interface{}) bool) Query

SkipWhileIndexed bypasses elements in a collection 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.

This method tests each element by using predicate and skips the element if the result is true. After the predicate function returns false for an element, that element and the remaining elements in source are returned and there are no more invocations of predicate.

Example

The following code example demonstrates how to use SkipWhileIndexed to skip elements of an array as long as a condition that depends on the element's index is true.

amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500}

var query []int
From(amounts).
	SkipWhileIndexed(
		func(index int, amount interface{}) bool { return amount.(int) > index*1000 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[4000 1500 5500]

func (Query) SkipWhileIndexedT

func (q Query) SkipWhileIndexedT(predicateFn interface{}) Query

SkipWhileIndexedT is the typed version of SkipWhileIndexed.

  • predicateFn is of type "func(int,TSource)bool"

NOTE: SkipWhileIndexed has better performance than SkipWhileIndexedT.

Example

The following code example demonstrates how to use SkipWhileIndexedT to skip elements of an array as long as a condition that depends on the element's index is true.

amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500}

var query []int
From(amounts).
	SkipWhileIndexedT(
		func(index int, amount int) bool { return amount > index*1000 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[4000 1500 5500]

func (Query) SkipWhileT

func (q Query) SkipWhileT(predicateFn interface{}) Query

SkipWhileT is the typed version of SkipWhile.

  • predicateFn is of type "func(TSource)bool"

NOTE: SkipWhile has better performance than SkipWhileT.

Example

The following code example demonstrates how to use SkipWhileT to skip elements of an array as long as a condition is true.

grades := []int{59, 82, 70, 56, 92, 98, 85}
var lowerGrades []int
From(grades).
	OrderByDescendingT(
		func(g int) int { return g },
	).
	SkipWhileT(
		func(g int) bool { return g >= 80 },
	).
	ToSlice(&lowerGrades)

//"All grades below 80:
fmt.Println(lowerGrades)
Output:

[70 59 56]

func (Query) Sort

func (q Query) Sort(less func(i, j interface{}) bool) Query

Sort returns a new query by sorting elements with provided less function in ascending order. The comparer function should return true if the parameter i is less than j. While this method is uglier than chaining OrderBy, OrderByDescending, ThenBy and ThenByDescending methods, it's performance is much better.

Example

The following code example demonstrates how to use Sort to order elements of an slice.

amounts := []int{5000, 2500, 9000, 8000, 6500, 4000, 1500, 5500}

var query []int
From(amounts).
	Sort(
		func(i interface{}, j interface{}) bool { return i.(int) < j.(int) },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[1500 2500 4000 5000 5500 6500 8000 9000]

func (Query) SortT

func (q Query) SortT(lessFn interface{}) Query

SortT is the typed version of Sort.

  • lessFn is of type "func(TSource,TSource) bool"

NOTE: Sort has better performance than SortT.

Example

The following code example demonstrates how to use SortT to order elements of an slice.

type Pet struct {
	Name string
	Age  int
}
// Create a list of pets.
pets := []Pet{
	{Name: "Barley", Age: 8},
	{Name: "Boots", Age: 4},
	{Name: "Whiskers", Age: 1},
	{Name: "Daisy", Age: 4},
}

orderedPets := []Pet{}
From(pets).
	SortT(
		func(pet1 Pet, pet2 Pet) bool { return pet1.Age < pet2.Age },
	).
	ToSlice(&orderedPets)

for _, pet := range orderedPets {
	fmt.Println(pet.Name, "-", pet.Age)
}
Output:

Whiskers - 1
Boots - 4
Daisy - 4
Barley - 8

func (Query) SumFloats

func (q Query) SumFloats() (r float64)

SumFloats computes the sum of a collection of numeric values.

Values can be of any float type: float32 or float64. The result is float64. Method returns zero if collection contains no elements.

Example

The following code example demonstrates how to use SumFloats to sum the values of a slice.

numbers := []float64{43.68, 1.25, 583.7, 6.5}

sum := From(numbers).SumFloats()

fmt.Printf("The sum of the numbers is %f.", sum)
Output:

The sum of the numbers is 635.130000.

func (Query) SumInts

func (q Query) SumInts() (r int64)

SumInts computes the sum of a collection of numeric values.

Values can be of any integer type: int, int8, int16, int32, int64. The result is int64. Method returns zero if collection contains no elements.

Example

The following code example demonstrates how to use SumInts to sum the values of a slice.

numbers := []int{43, 1, 583, 6}

sum := From(numbers).SumInts()

fmt.Printf("The sum of the numbers is %d.", sum)
Output:

The sum of the numbers is 633.

func (Query) SumUInts

func (q Query) SumUInts() (r uint64)

SumUInts computes the sum of a collection of numeric values.

Values can be of any unsigned integer type: uint, uint8, uint16, uint32, uint64. The result is uint64. Method returns zero if collection contains no elements.

Example

The following code example demonstrates how to use SumUInts to sum the values of a slice.

numbers := []uint{43, 1, 583, 6}

sum := From(numbers).SumUInts()

fmt.Printf("The sum of the numbers is %d.", sum)
Output:

The sum of the numbers is 633.

func (Query) Take

func (q Query) Take(count int) Query

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

Example

The following code example demonstrates how to use Take

to return elements from the start of a slice.
grades := []int{59, 82, 70, 56, 92, 98, 85}

var topThreeGrades []int
From(grades).
	OrderByDescending(
		func(grade interface{}) interface{} { return grade },
	).
	Take(3).
	ToSlice(&topThreeGrades)

fmt.Printf("The top three grades are: %v", topThreeGrades)
Output:

The top three grades are: [98 92 85]

func (Query) TakeWhile

func (q Query) TakeWhile(predicate func(interface{}) bool) Query

TakeWhile returns elements from a collection as long as a specified condition is true, and then skips the remaining elements.

Example

The following code example demonstrates how to use TakeWhile to return elements from the start of a slice.

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

var query []string
From(fruits).
	TakeWhile(
		func(fruit interface{}) bool { return fruit.(string) != "orange" },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[apple banana mango]

func (Query) TakeWhileIndexed

func (q Query) TakeWhileIndexed(predicate func(int, interface{}) bool) Query

TakeWhileIndexed returns elements from a collection as long as a specified condition is true. The element's index is used in the logic of the predicate function. The first argument of predicate represents the zero-based index of the element within collection. The second argument represents the element to test.

Example

The following code example demonstrates how to use TakeWhileIndexed to return elements from the start of a slice as long as a condition that uses the element's index is true.

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

var query []string
From(fruits).
	TakeWhileIndexed(
		func(index int, fruit interface{}) bool { return len(fruit.(string)) >= index },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[apple passionfruit banana mango orange blueberry]

func (Query) TakeWhileIndexedT

func (q Query) TakeWhileIndexedT(predicateFn interface{}) Query

TakeWhileIndexedT is the typed version of TakeWhileIndexed.

  • predicateFn is of type "func(int,TSource)bool"

NOTE: TakeWhileIndexed has better performance than TakeWhileIndexedT.

Example

The following code example demonstrates how to use TakeWhileIndexedT to return elements from the start of a slice as long asa condition that uses the element's index is true.

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

var query []string
From(fruits).
	TakeWhileIndexedT(
		func(index int, fruit string) bool { return len(fruit) >= index },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[apple passionfruit banana mango orange blueberry]

func (Query) TakeWhileT

func (q Query) TakeWhileT(predicateFn interface{}) Query

TakeWhileT is the typed version of TakeWhile.

  • predicateFn is of type "func(TSource)bool"

NOTE: TakeWhile has better performance than TakeWhileT.

Example

The following code example demonstrates how to use TakeWhileT to return elements from the start of a slice.

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

var query []string
From(fruits).
	TakeWhileT(
		func(fruit string) bool { return fruit != "orange" },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[apple banana mango]

func (Query) ToChannel

func (q Query) ToChannel(result chan<- interface{})

ToChannel iterates over a collection and outputs each element to a channel, then closes it.

Example

The following code example demonstrates how to use ToChannel to send a slice to a channel.

c := make(chan interface{})

go func() {
	Repeat(10, 3).ToChannel(c)
}()

for i := range c {
	fmt.Println(i)
}
Output:

10
10
10

func (Query) ToMap

func (q Query) ToMap(result interface{})

ToMap iterates over a collection and populates result map with elements. Collection elements have to be of KeyValue type to use this method. To populate a map with elements of different type use ToMapBy method. ToMap doesn't empty the result map before populating it.

Example

The following code example demonstrates how to use ToMap to populate a map.

type Product struct {
	Name string
	Code int
}

products := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

map1 := map[int]string{}
From(products).
	SelectT(
		func(item Product) KeyValue { return KeyValue{Key: item.Code, Value: item.Name} },
	).
	ToMap(&map1)

fmt.Println(map1[4])
fmt.Println(map1[9])
fmt.Println(map1[12])
Output:

orange
apple
lemon

func (Query) ToMapBy

func (q Query) ToMapBy(result interface{},
	keySelector func(interface{}) interface{},
	valueSelector func(interface{}) interface{})

ToMapBy iterates over a collection and populates the result map with elements. Functions keySelector and valueSelector are executed for each element of the collection to generate key and value for the map. Generated key and value types must be assignable to the map's key and value types. ToMapBy doesn't empty the result map before populating it.

Example

The following code example demonstrates how to use ToMapBy by using a key and value selectors to populate a map.

input := [][]interface{}{{1, true}}

result := make(map[int]bool)
From(input).
	ToMapBy(&result,
		func(i interface{}) interface{} {
			return i.([]interface{})[0]
		},
		func(i interface{}) interface{} {
			return i.([]interface{})[1]
		},
	)

fmt.Println(result)
Output:

map[1:true]

func (Query) ToMapByT

func (q Query) ToMapByT(result interface{},
	keySelectorFn interface{}, valueSelectorFn interface{})

ToMapByT is the typed version of ToMapBy.

  • keySelectorFn is of type "func(TSource)TKey"
  • valueSelectorFn is of type "func(TSource)TValue"

NOTE: ToMapBy has better performance than ToMapByT.

Example

The following code example demonstrates how to use ToMapBy by using a key and value selectors to populate a map.

type Product struct {
	Name string
	Code int
}

products := []Product{
	{Name: "orange", Code: 4},
	{Name: "apple", Code: 9},
	{Name: "lemon", Code: 12},
	{Name: "apple", Code: 9},
}

map1 := map[int]string{}
From(products).
	ToMapByT(&map1,
		func(item Product) int { return item.Code },
		func(item Product) string { return item.Name },
	)

fmt.Println(map1[4])
fmt.Println(map1[9])
fmt.Println(map1[12])
Output:

orange
apple
lemon

func (Query) ToSlice

func (q Query) ToSlice(v interface{})

ToSlice iterates over a collection and saves the results in the slice pointed by v. It overwrites the existing slice, starting from index 0.

If the slice pointed by v has sufficient capacity, v will be pointed to a resliced slice. If it does not, a new underlying array will be allocated and v will point to it.

Example

The following code example demonstrates how to use ToSlice to populate a slice.

var result []int
Range(1, 10).ToSlice(&result)

fmt.Println(result)
Output:

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

func (Query) Union

func (q Query) Union(q2 Query) Query

Union produces the set union of two collections.

This method excludes duplicates from the return set. This is different behavior to the Concat method, which returns all the elements in the input collection including duplicates.

Example

The following code example demonstrates how to use Union to obtain the union of two slices of integers.

q := Range(1, 10).Union(Range(6, 10))

fmt.Println(q.Results())
Output:

[1 2 3 4 5 6 7 8 9 10 11 12 13 14 15]

func (Query) Where

func (q Query) Where(predicate func(interface{}) bool) Query

Where filters a collection of values based on a predicate.

Example

The following code example demonstrates how to use Where to filter a slices.

fruits := []string{"apple", "passionfruit", "banana", "mango",
	"orange", "blueberry", "grape", "strawberry"}
var query []string
From(fruits).
	Where(
		func(f interface{}) bool { return len(f.(string)) > 6 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[passionfruit blueberry strawberry]

func (Query) WhereIndexed

func (q Query) WhereIndexed(predicate func(int, interface{}) bool) Query

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

The first argument represents the zero-based index of the element within collection. The second argument of predicate represents the element to test.

Example

The following code example demonstrates how to use WhereIndexed to filter a slice based on a predicate that involves the index of each element.

numbers := []int{0, 30, 20, 15, 90, 85, 40, 75}

var query []int
From(numbers).
	WhereIndexed(
		func(index int, number interface{}) bool { return number.(int) <= index*10 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[0 15 40]

func (Query) WhereIndexedT

func (q Query) WhereIndexedT(predicateFn interface{}) Query

WhereIndexedT is the typed version of WhereIndexed.

  • predicateFn is of type "func(int,TSource)bool"

NOTE: WhereIndexed has better performance than WhereIndexedT.

Example

The following code example demonstrates how to use WhereIndexedT to filter a slice based on a predicate that involves the index of each element.

numbers := []int{0, 30, 20, 15, 90, 85, 40, 75}

var query []int
From(numbers).
	WhereIndexedT(
		func(index int, number int) bool { return number <= index*10 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[0 15 40]

func (Query) WhereT

func (q Query) WhereT(predicateFn interface{}) Query

WhereT is the typed version of Where.

  • predicateFn is of type "func(TSource)bool"

NOTE: Where has better performance than WhereT.

Example

The following code example demonstrates how to use WhereT to filter a slices.

fruits := []string{"apple", "passionfruit", "banana", "mango",
	"orange", "blueberry", "grape", "strawberry"}
var query []string
From(fruits).
	WhereT(
		func(f string) bool { return len(f) > 6 },
	).
	ToSlice(&query)

fmt.Println(query)
Output:

[passionfruit blueberry strawberry]

func (Query) Zip

func (q Query) Zip(q2 Query,
	resultSelector func(interface{}, interface{}) interface{}) Query

Zip applies a specified function to the corresponding elements of two collections, producing a collection of the results.

The method steps through the two input collections, applying function resultSelector to corresponding elements of the two collections. The method returns a collection of the values that are returned by resultSelector. If the input collections do not have the same number of elements, the method combines elements until it reaches the end of one of the collections. For example, if one collection has three elements and the other one has four, the result collection has only three elements.

Example

The following code example demonstrates how to use the Zip method to merge two slices.

number := []int{1, 2, 3, 4, 5}
words := []string{"one", "two", "three"}

q := From(number).
	Zip(From(words),
		func(a interface{}, b interface{}) interface{} { return []interface{}{a, b} },
	)

fmt.Println(q.Results())
Output:

[[1 one] [2 two] [3 three]]

func (Query) ZipT

func (q Query) ZipT(q2 Query,
	resultSelectorFn interface{}) Query

ZipT is the typed version of Zip.

  • resultSelectorFn is of type "func(TFirst,TSecond)TResult"

NOTE: Zip has better performance than ZipT.

Example

The following code example demonstrates how to use the Zip method to merge two slices.

number := []int{1, 2, 3, 4, 5}
words := []string{"one", "two", "three"}

q := From(number).
	ZipT(From(words),
		func(a int, b string) []interface{} { return []interface{}{a, b} },
	)

fmt.Println(q.Results())
Output:

[[1 one] [2 two] [3 three]]

Jump to

Keyboard shortcuts

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