Analysis of go LINQ package method

Note: all of the following methods come from https://github.com/ahmetb/go-linq , only the usage of corresponding methods is analyzed

Specific use examples can be referred to https://godoc.org/github.com/ahmetb/go-linq#

catalogue

Ⅰ. Front: structure and data construction method

Ⅱ. Method usage parsing

1. Aggregate: Custom aggregate operation

2. All: judge whether all elements meet the conditions

3. Any: judge whether any element satisfies the condition

4. Where: query all corresponding elements according to criteria

5. Function of calculation type

6. Combine two arrays or add elements

7. Contains: judge whether the element is in the Query

8. First, Last: first, Last

9. Distinct: filter the array to make all elements unique

10. Except ion: find the difference set

11. GroupBy: Group

12. Intersect: find intersection

13. OrderBy: sort

14. Skip: skip elements that meet the specified criteria

15. Count: calculates the length of the array

16. ToMap: convert to Map

17. ToSlice: convert to array

18. Take: extract the corresponding number of elements

19. Select: filter structure field / rule operation

20. SelectMany: flatten multidimensional array

21. Join: associated structure

Ⅲ. matters needing attention

Ⅰ. Front: structure and data construction method

type Book struct {
	Name        string
	Author      string
	Money       float64
	WordsNum    int
	PublishTime time.Time
}


type Person struct {
	Name string //Owner's name
}

type Pet struct {
	Name      string //Animal names
	OwnerName string //Owner's name
}

type Man struct {
	Name string //Owner's name
	Pets []Pets //Pets
}

type Pets struct {
	Name string //Animal names
}
func MakeInnerData() []Man {
	man := make([]Man, 0)
	man = append(man, Man{
		Name: "Kang Kang",
		Pets: []Pets{{Name: "Kangkang's dog"}, {Name: "Kangkang's cat"}},
	})
	man = append(man, Man{
		Name: "Lao Shi",
		Pets: []Pets{{Name: "Lao Shi's🐟"}, {Name: "Lao Shi's bird"}},
	})
	man = append(man, Man{
		Name: "Xiao Ming",
		Pets: []Pets{{Name: "Xiao Ming🐖"}, {Name: "Xiao Ming's dog"}},
	})

	return man
}

func MakeJoinData() ([]Person, []Pet) {
	kangkang := Person{Name: "Love to eat happy Kangkang"}
	laoshi := Person{Name: "Lao Shi"}
	xiaoming := Person{Name: "Don't rush-Xiao Ming"}
	expect := Person{Name: "I have no pets"}

	dog := Pet{Name: "Kangkang's dog", OwnerName: kangkang.Name}
	cat := Pet{Name: "Kangkang's cat", OwnerName: kangkang.Name}
	fish := Pet{Name: "Lao Shi's🐟", OwnerName: laoshi.Name}
	pig := Pet{Name: "Xiao Ming🐖", OwnerName: xiaoming.Name}

	return []Person{kangkang, laoshi, xiaoming, expect}, []Pet{dog, cat, fish, pig}
}




func MakeBook() []Book {
	bookList := make([]Book, 0)
	bookList = append(bookList, Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Effective Java",
		Author:      "Java",
		Money:       78,
		WordsNum:    9000,
		PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Java language",
		Author:      "Java",
		Money:       50,
		WordsNum:    3000,
		PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Lua language",
		Author:      "Lua",
		Money:       75,
		WordsNum:    45000,
		PublishTime: time.Date(2020, 1, 10, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "React language",
		Author:      "React",
		Money:       99,
		WordsNum:    14500,
		PublishTime: time.Date(2020, 7, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Red language",
		Author:      "Red",
		Money:       28,
		WordsNum:    880,
		PublishTime: time.Date(2019, 4, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "JavaScript language",
		Author:      "JavaScript",
		Money:       81,
		WordsNum:    3776,
		PublishTime: time.Date(2019, 5, 17, 10, 0, 0, 0, time.Local),
	})
	return bookList
}

func MakeBook1() []Book {
	bookList := make([]Book, 0)
	bookList = append(bookList, Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Effective Java",
		Author:      "Java",
		Money:       78,
		WordsNum:    9000,
		PublishTime: time.Date(2020, 2, 15, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Go language(Second Edition)",
		Author:      "Go",
		Money:       50,
		WordsNum:    3000,
		PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
	})
	return bookList
}
func MakeBook2() []Book {
	bookList := make([]Book, 0)
	bookList = append(bookList, Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	return bookList
}

func MakeBook3() []Book {
	bookList := make([]Book, 0)
	bookList = append(bookList, Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	bookList = append(bookList, Book{
		Name:        "Go language(Third Edition)",
		Author:      "Go",
		Money:       50,
		WordsNum:    3000,
		PublishTime: time.Date(2020, 2, 1, 10, 0, 0, 0, time.Local),
	})
	return bookList
}

 

Ⅱ. Method usage parsing

1. Aggregate: Custom aggregate operation

The user-defined aggregation method provides two variants, one is the , Aggregate method that supports fixed types, and the other is the , Aggregate method that supports interface s.

Aggregate provides a method that supports two parameters:

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

This method is the specific method of aggregation operation. The use examples here are as follows:

func Aggregate() {
	bookList := MakeBook()
	query := linq.From(bookList)
	// The aggregation operation here is actually user defined corresponding comparison method.
	// According to the comments, the first element of the array is obtained for the first time, and then compared with the second element. If the second element meets the conditions, then [replace the first element]. Otherwise, the current aggregation operation still holds the first element.
	// And so on
	result := query.Aggregate(AggregateFunc).(Book)
	fmt.Println(fmt.Sprintf("The query result of aggregation operation is[%s]This book was first published:%v", result.Name, timed.GetTimeDefaultFormatString(result.PublishTime.Unix())))
}


//Custom aggregation operation method
var AggregateFunc = func(first interface{}, second interface{}) interface{} {
	if first.(Book).PublishTime.Before(second.(Book).PublishTime) {
		return first
	}
	return second
}

The AggregateT method supports a custom type of input parameter, as follows:

// AggregateT is the typed version of Aggregate.
//
//   - f is of type: func(TSource, TSource) TSource
//
// NOTE: Aggregate has better performance than AggregateT.
func (q Query) AggregateT(f interface{}) interface{} 

Similarly, in addition to method customization, two input parameters are also supported here. The specific use examples are similar to those above

 

2. All: judge whether all elements meet the conditions

All provides two methods

One is to support specific types of AllT methods,

One is the All method supporting interface, and the input parameter is a condition method of predicate, that is, to return the result of whether All elements meet the condition, true or false

// All determines whether all elements of a collection satisfy a condition.
func (q Query) All(predicate func(interface{}) bool) bool 

The use examples here are:

func All() {
	bookList := MakeBook()
	query := linq.From(bookList)
	result := query.All(PublishTimeBeforeFunc)
	fmt.Println(fmt.Sprintf("Whether all the books are published earlier than January 1, 2020, the answer is%v", result))

	result = query.All(PublishTimeAfterFunc)
	fmt.Println(fmt.Sprintf("Whether all the books are published later than January 1, 2018, the answer is%v", result))
}

3. Any: judge whether any element satisfies the condition

Three methods are provided here: Any, AnyWith and AnyWithT

Any method returns the result of whether the element exists (true, false)

AnyWith and AnyWithT, according to the passed judgment conditions, return the result of whether the element meeting the judgment conditions is greater than or equal to 1 (true, false)

Specific examples are as follows:

func AnyWith() {
	bookList := MakeBook()
	query := linq.From(bookList)
	result := query.AnyWith(PublishTimeBeforeFunc) //Judge whether any element meets the condition
	fmt.Println(fmt.Sprintf("Is there any book published earlier than January 1, 2020? The answer is%v", result))

	result = query.AnyWith(PublishTimeAfterFunc2) //Judge whether any element meets the condition
	fmt.Println(fmt.Sprintf("Is there any book published later than January 1, 2021? The answer is%v", result))
}

4. Where: query all corresponding elements according to criteria

The Where method queries all elements that meet the conditions through condition judgment. Two methods, Where and Where, are also provided here. Specific examples are as follows:

func Where() {
	bookList := MakeBook()
	query := linq.From(bookList)
	fmt.Println()
	fmt.Println()
	query.WhereT(func(book Book) bool {
		return book.Money > float64(70)
	}).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", book.Author, book.Name))
	})
}

5. Function of calculation type

Functions of calculation type are mainly introduced here: Average, Max and Min. the type passed in must be number, otherwise an error will be reported, because the specific processing is also through switch operation Cannot handle non number types. Specific examples are as follows:

func Calculate() {
	query := linq.From([]int{1, 2, 3, 4, 5, 6, 7, 8, 9})
	fmt.Println(fmt.Sprintf("The average value is:%f", query.Average()))
	fmt.Println(fmt.Sprintf("The maximum value is%d", query.Max()))
	fmt.Println(fmt.Sprintf("The minimum value is%d", query.Min()))
}

6. Combine two arrays or add elements

Combining two arrays provides two methods:

Concat: the duplicate elements in two queries will be excluded

Union: duplicate elements in two queries will not be excluded. The number of elements will be combined into a Query of as many elements

There are also two methods for adding elements:

Append: adds the new element to the last position of the Query

PrePend: add the new element to the first position of Query

Specific examples are:

func Combine() {
	bookList := MakeBook()
	query := linq.From(bookList)
	query1 := query.Concat(query) //Duplicates will not be excluded
	query2 := query.Union(query)  //Duplicates are excluded
	fmt.Println(fmt.Sprintf("The number of elements returned by methods that do not exclude duplicates is%d", len(query1.Results())))
	fmt.Println(fmt.Sprintf("The number of elements returned by the method that will exclude duplicates is%d", len(query2.Results())))
	query1 = query1.Append(Book{Name: "Last One"})   //Add to the end of the original Query
	query2 = query2.Prepend(Book{Name: "First One"}) //Added to the first of the original Query
	fmt.Println(fmt.Sprintf("The last element is%v", query1.Last()))
	fmt.Println(fmt.Sprintf("The first element is%v", query2.First()))
}

It should be noted that after calling the corresponding method, the query must be assigned to a new query (with an equal sign) in order to get the corresponding result

 

7. Contains: judge whether the element is in the Query

It should be noted that when Go judges the operation of element equals, what needs to be put into Query should be the structure array, not the pointer array. If it is the pointer array, it judges the pointer address. If it is a structure array, according to the judgment of Go, if all element values are equal, the structure is equal

The specific usage of Contains is as follows:

func Contains() {
	bookList := MakeBook()
	query := linq.From(bookList)
	//It should be noted here that if you want to judge whether two elements are equal, the address of the element cannot be used in go
	// Therefore, what is added to the query here must not be the address of the element, otherwise there is no way to compare the structure itself, but the address of the structure
	fmt.Println(fmt.Sprintf("Determine whether the current array contains the same elements,All values, not addresses, are judged, and the result is%v", query.Contains(Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})))
}

 

8. First, Last: first, Last

First and Last provide three methods respectively:

First returns the first element of the array in the Query

FirstWith, FirstWithT: returns the first element of the Query array that meets the conditions

Last returns the last element of the array in the Query

LastWith, LastWithT: returns the last element of the Query array that meets the conditions

Specific examples are as follows:

func FirstAndLast() {
	bookList := MakeBook()
	query := linq.From(bookList)
	fmt.Println(fmt.Sprintf("The first book in the array is called:%s", query.First().(Book).Name))
	fmt.Println(fmt.Sprintf("The first book in the array was published before January 1, 2020:%s", query.FirstWith(PublishTimeBeforeFunc).(Book).Name))

	fmt.Println(fmt.Sprintf("The last book in the array is called:%s", query.Last().(Book).Name))
	fmt.Println(fmt.Sprintf("The last book in the array was published before January 1, 2020:%s", query.LastWith(PublishTimeBeforeFunc).(Book).Name))
}

9. Distinct: filter the array to make all elements unique

Distinct provides three methods

Distinct: judge whether structures are equal and return all unique structures

Distinguishby, distinguishbyt: judge whether they are equal according to the corresponding fields and return a unique structure

Examples are as follows:

func Distinct() {
	bookList := MakeBook()
	query := linq.From(bookList)
	query = query.Append(Book{
		Name:        "Go language",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	bookList1 := make([]Book, 0)
	query.ToSlice(&bookList1)
	fmt.Println(fmt.Sprintf("Before filtering query In total%d Data", query.Count()))
	//If the distinct here is a structure, it judges all the values of the structure. If it is a pointer, it judges the pointer address
	query = query.Distinct()
	fmt.Println(fmt.Sprintf("After screening query In total%d Data", query.Count()))

	fmt.Println()
	fmt.Println("Output corresponding book title and author")
	query = query.Append(Book{
		Name:        "Go language(Second Edition)",
		Author:      "Go",
		Money:       100,
		WordsNum:    1000,
		PublishTime: time.Date(2020, 1, 1, 10, 0, 0, 0, time.Local),
	})
	//Judge whether the corresponding fields are the same according to the corresponding rules -- if the corresponding fields are the same, only the first one found will be retained and the later ones will be cleared
	query.DistinctByT(func(book Book) string {
		return book.Author
	}).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})
}

10. Except ion: find the difference set

Except ion provides two methods:

Except ion: filter the difference set between two queries according to the structure

ExceptBy: filter the difference set between two queries according to the fields of the structure

In fact, here is to find the elements in Query1 but not in Query2. Specific examples are as follows:

func Except() {
	bookList1 := MakeBook1()
	query1 := linq.From(bookList1)
	bookList2 := MakeBook2()
	query2 := linq.From(bookList2)

	fmt.Println("Output corresponding book title and author")
	//Judge whether the structure itself is equal
	query1.Except(query2).
		ForEachT(func(book Book) {
			fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
		})

	fmt.Println()
	fmt.Println("Output corresponding book title and author")
	//Judge whether a field of the structure appears
	query1.ExceptByT(query2, func(book Book) string {
		return book.Author
	}).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})
}

                 

11. GroupBy: Group

GroupBy provides two methods, GroupByT method and GroupBy method of user-defined structure.

The two methods directly specify the key and Group corresponding to the Group For grouped elements, a field in the structure can be used as its key, and the grouping result can be a structure, a field or a rule

Specific examples are as follows:

func GroupBy() {
	bookList1 := MakeBook1()
	query := linq.From(bookList1)

	fmt.Println("Output corresponding book title and author")
	//The first func is the basis of grouping, and the second func is the element returned after grouping
	query = query.GroupByT(func(book Book) string {
		return book.Author
	}, func(book Book) Book {
		return book
	})

	query.ForEachT(func(bookGroup linq.Group) {
		fmt.Println(fmt.Sprintf("The author is%v", bookGroup.Key))
		for _, item := range bookGroup.Group {
			fmt.Println(fmt.Sprintf("title%v,author%v", item.(Book).Name, item.(Book).Author))
			fmt.Println()
		}

	})
	fmt.Println()
	fmt.Println("Output corresponding book title")

	bookList1 = MakeBook1()
	query = linq.From(bookList1)
	var nameGroups []linq.Group
	query.GroupByT(
		func(book Book) string { return book.Author },
		func(book Book) string { return book.Name },
	).ToSlice(&nameGroups)

	for _, item := range nameGroups {
		fmt.Println(fmt.Sprintf("The author is%v", item.Key))
		for _, row := range item.Group {
			fmt.Println(fmt.Sprintf("title%v", row))
		}
	}
}

12. Intersect: find intersection

Intersect provides three methods

Intersect: calculate the intersection according to the judgment of the structure

IntersectBy, IntersectByT: judge the intersection according to the structure field or rule

Specific examples are as follows:

func Intersect() {
	bookList1 := MakeBook1()
	query1 := linq.From(bookList1)
	bookList2 := MakeBook2()
	query2 := linq.From(bookList2)

	fmt.Println("Output the corresponding book elements and judge the intersection according to the structure")
	query3 := query1.Intersect(query2)
	query3.ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})

	fmt.Println()
	fmt.Println("Output the corresponding book elements and judge the intersection according to the elements")
	query3 = query1.IntersectByT(query2, func(book Book) string {
		return book.Author
	})
	query3.ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})

	//The calculation here is based on an element of the structure. It turns out that the returned elements are exactly the same whether they are filtered according to the elements of the structure or not
	fmt.Println()
	fmt.Println("Output the corresponding book elements and judge the intersection 2 according to the elements")
	bookList1 = MakeBook1()
	query1 = linq.From(bookList1)
	bookList3 := MakeBook3()
	query2 = linq.From(bookList3)
	query3 = query2.IntersectByT(query1, func(book Book) string {
		return book.Author
	})
	query3.ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})

	fmt.Println()
	fmt.Println("Determine whether there will be no repeated processing")
	query1 = linq.From([]int{1, 2, 3, 4, 5, 3})
	query2 = linq.From([]int{1, 3, 3, 78, 99, 0, 111})
	query3 = query2.IntersectByT(query1, func(i int) int {
		return i
	})
	fmt.Println(query3.Results())
}

13. OrderBy: sort

linq provides several sorting methods, including the secondary sorting method

Order from small to large: Orderby, OrderByT

The order is from large to small: OrderByDescending, OrderByDescending t

Based on the previous sorting, they are sorted from small to large: ThenBy and ThenByT

On the basis of the previous sorting, they are sorted from large to small: ThenByDescending, ThenByDescending t

Specific examples are as follows:

//OrderBy can be sorted according to the corresponding rules, and multiple sorting can be realized. It should be noted that OrderBy is from arrival and orderByDescending is from large to small
func OrderBy() {
	bookList := MakeBook()
	query := linq.From(bookList)
	query = query.OrderByDescendingT(func(book Book) string {
		return book.Name
	}).ThenByDescendingT(func(book Book) string {
		return book.Author
	}).ThenByDescendingT(func(book Book) float64 {
		return book.Money
	}).Query

	query.ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})

	fmt.Println()
	fmt.Println()

	//Reverse: reverse the results
	query.Reverse().ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("title%v,author%v", book.Name, book.Author))
	})
}

14. Skip: skip elements that meet the specified criteria

Skip provides three methods:

Skip (num): skip the number of elements and take the remaining elements

SkipWhile (predict), SkipWhileT (predict): ignore the corresponding array elements that meet the conditions and take the remaining elements

Specific examples are as follows:

func Skip() {
	bookList := MakeBook()
	query := linq.From(bookList)

	fmt.Println(fmt.Sprintf("Skip three elements and return an array containing%d Elements", len(query.Skip(3).Results())))
	fmt.Println(fmt.Sprintf("Skip release time in 2018.1.1 After the element, the returned array contains%d Elements", query.SkipWhile(PublishTimeAfterFunc).Count()))
}

15. Count: calculates the length of the array

Count provides three methods:

Count: calculate the length of the array carried by the current Query

CountWith, CountWithT: calculate the length of the array carried by the current Query that meets the conditions

Specific examples are as follows:

func Count() {
	bookList := MakeBook()
	query := linq.From(bookList)
	fmt.Println(fmt.Sprintf("The publication time in the array is earlier than 2019-1-1 My books are%d book", query.CountWithT(PublishTimeBeforeFunc)))
	fmt.Println(fmt.Sprintf("The publication time in the array is later than 2018-1-1 My books are%d book", query.CountWithT(PublishTimeAfterFunc)))
}

 

16. ToMap: convert to Map

ToMap provides three methods

ToMap: it needs to cooperate with the SelectT method to generate and return a LINQ The structure of keyValue, specifying the key and value of the corresponding Map

ToMapBy and ToMapByT: two methods are provided. One method specifies key and the other method specifies value

If the key s are the same, the previous elements will be overwritten. The use of the ToMap method needs to cooperate with the Select method

Specific examples are as follows:

func ToMap() {
	bookList := MakeBook()
	query := linq.From(bookList)

	bookMap := make(map[string]string, 0)
	query.SelectT(func(book Book) linq.KeyValue {
		return linq.KeyValue{
			Key:   book.Author,
			Value: book.Name,
		}
	}).ToMap(&bookMap)

	for key, value := range bookMap {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", key, value))
	}

	fmt.Println()
	fmt.Println()

	//If the key s are the same, the previous elements will be overwritten (only the last one will be retained)
	bookList1 := MakeBook1()
	query1 := linq.From(bookList1)
	bookMap1 := make(map[string]string, 0)
	query1.SelectT(func(book Book) linq.KeyValue {
		return linq.KeyValue{
			Key:   book.Author,
			Value: book.Name,
		}
	}).ToMap(&bookMap1)

	for key, value := range bookMap1 {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", key, value))
	}

	fmt.Println()
	fmt.Println()
	bookList2 := MakeBook()
	query2 := linq.From(bookList2)

	bookMap2 := make(map[string]Book, 0)
	query2.ToMapByT(&bookMap2,
		//This method determines the field of the key
		func(book Book) string {
			return book.Author
		}, //This method determines what the value field is
		func(book Book) Book {
			return book
		})

	for key, value := range bookMap2 {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", key, value.Name))
	}
}

17. ToSlice: convert to array

ToSlice provides methods to convert arrays. Specific examples are as follows:

func ToSlice(){
	fmt.Println()
	fmt.Println()
	bookListResult := make([]Book,0)
	linq.From(MakeBook()).OrderByDescendingT(func(book Book) string {
		return book.Author
	}).ToSlice(&bookListResult)
	for _, value := range bookListResult {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", value.Author, value.Name))
	}
}

18. Take: extract the corresponding number of elements

The Take method provides three methods:

Take(num): extract the corresponding number of elements

Take while, take while t (predict): extract the elements that meet the conditions. Once an element does not meet the conditions, it will return directly without judging the following elements

Once TakeWhile encounters an element that does not meet the conditions, it will return directly and will not look down. Be sure to pay attention to this, otherwise it is likely to make mistakes when using it

Specific examples are as follows:

func Take() {
	bookList := MakeBook()
	query := linq.From(bookList)
	query.OrderByDescendingT(func(book Book) string {
		return book.Author
	}).Take(3).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", book.Author, book.Name))
	})

	fmt.Println()
	fmt.Println()

	//Will an error be reported if the number of elements exceeds the corresponding number (output all elements)
	query.OrderByDescendingT(func(book Book) string {
		return book.Author
	}).Take(100).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", book.Author, book.Name))
	})

	fmt.Println()
	fmt.Println()
	//What happens to negative numbers (return directly without operation)
	query.OrderByDescendingT(func(book Book) string {
		return book.Author
	}).Take(-2).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", book.Author, book.Name))
	})

	//Although the TakeWhile series of methods can query according to the conditions, one disadvantage is that once the query results do not meet the conditions, they will be returned directly, that is, the elements that meet the conditions will not be filtered
	//For example, for the greater than operation here, you need to sort the entire array and then filter it. If you don't want to sort, it may be better to use the native for loop
	fmt.Println()
	fmt.Println()
	query.TakeWhileT(func(book Book) bool {
		return book.Money > float64(70)
	}).ForEachT(func(book Book) {
		fmt.Println(fmt.Sprintf("author%v,Wrote a book called%v", book.Author, book.Name))
	})
}

19. Select: filter structure field / rule operation

Select provides four methods, which are mainly used to process and filter structure fields, as follows:

Select, SelectT: filter the corresponding fields.

SelectIndexd, SelectIndexdT: filter the corresponding fields, where you can get the subscript information of the corresponding structure.

Specific examples are as follows:

func Select() {
	bookList := MakeBook()
	query := linq.From(bookList)

	//Filter out the elements corresponding to the structure
	query.SelectT(func(book Book) string {
		return book.Name
	}).ForEachT(func(bookName string) {
		fmt.Println(fmt.Sprintf("title%v", bookName))
	})

	fmt.Println()
	fmt.Println()

	//Return according to the subscript. If it is related to the subscript, it can be combined and returned through this method
	query.SelectIndexedT(func(index int, book Book) []string {
		return []string{strconv.Itoa(index + 1), book.Name}
	}).ForEachT(func(book []string) {
		fmt.Println(fmt.Sprintf("The first%v This book,title%v", book[0], book[1]))
	})
}

20. SelectMany: flatten multidimensional array

SelectMany is mainly used to process multidimensional arrays or nested structures. Here are four methods:

SelectMany, SelectManyT: process multi-dimensional arrays, pass in a return LINQ The method of query object flattens the two-dimensional array into one-dimensional array after one time

SelectManyBy, SelectManyByT: project each element of the set into a Query, iterate and flatten the result set into a set, and call the result on each element. The more powerful one is to get the corresponding substructure in the structure array, and then get the substructure and the structure corresponding to the substructure through the second method for processing, See the following code for details:

func SelectMany() {
	input := [][]int{{1, 2, 3}, {4, 5, 6, 7}}

	//Merge binary arrays
	linq.From(input).SelectManyT(
		func(i []int) linq.Query {
			return linq.From(i)
		},
	).ForEachT(func(num int) {
		fmt.Println(num)
	})

	fmt.Println()
	fmt.Println()

	//Merge 3D arrays
	input1 := [][][]int{{{1, 2, 3}}, {{4, 5, 6, 7}, {8, 9, 10}}}
	linq.From(input1).SelectManyT(
		func(i [][]int) linq.Query {
			return linq.From(i)
		},
	).SelectManyT(
		func(i []int) linq.Query {
			return linq.From(i)
		},
	).ForEachT(func(num int) {
		fmt.Print(num)
		fmt.Print(" ")
	})

	//The main function of SelectMany is that the structure contains array elements. You can take out the array elements and do corresponding operations with the structure
	//If there are multiple arrays in the structure, you can put the corresponding multiple arrays into a newly defined structure array
	fmt.Println()
	men := MakeInnerData()
	linq.From(men).
		//The first method filters out the array corresponding to the structure
		SelectManyByT(func(man Man) linq.Query {
			return linq.From(man.Pets)
		},
			//The second method can get the data of the structure corresponding to the elements in the array
			func(pet Pets, man Man) map[string]Pets {
				return map[string]Pets{
					man.Name: pet,
				}
			}).ForEachT(func(petWithMan map[string]Pets) {
		for key, value := range petWithMan {
			fmt.Println(fmt.Sprintf("%v Have a pet. Its name is%v", key, value.Name))
		}
	})

}

21. Join: associated structure

Join is the operation of connecting two queries according to a field or a rule. Two methods are provided here

Join, join: the first input parameter is the connection field or rule of the element of Query1, and the second parameter is the connection field or rule corresponding to Query2. When the two rules are aligned, they can be connected The third parameter is func (the element corresponding to Query1 and the element corresponding to Query2). Because there may be no connection object here, pay attention to the handling of nil. The third method handles the elements on the two corresponding.

Specific code examples are as follows:

func Join() {
	//Tasks are related to animals. Find the corresponding relationship directly. Data without corresponding relationship will not be processed. Under normal circumstances, a single data should be used for correlation
	persons, pets := MakeJoinData()
	query1 := linq.From(persons)
	query2 := linq.From(pets)
	query1.JoinT(query2,
		func(person Person) string {
			return person.Name
		},
		func(pet Pet) string {
			return pet.OwnerName
		},
		func(person Person, pet Pet) map[string]Pet {
			petMap := make(map[string]Pet)
			petMap[person.Name] = pet
			return petMap
		},
	).ForEachT(func(petMap map[string]Pet) {
		for key, value := range petMap {
			fmt.Println(fmt.Sprintf("%v Have a pet. Its name is:%v", key, value.Name))
		}
	})
}

 

Ⅲ. matters needing attention

  1. Using methods that do not specify a type is more efficient than methods that specify a type. For example, Select is more efficient than SelectT, because SelectT also needs to generate the corresponding input parameter method according to the corresponding type, while Select does not need it, so it is more efficient
  2. ToMap,ToSlice,To... The input parameter of the method must be the structure pointer, otherwise there is no way to generate the corresponding attribute
  3. The TakeWhile method is a little similar to Where, but it should be noted that Where will return all elements that meet the conditions, while TakeWhile will return directly once it encounters elements that do not meet the conditions, and will not filter the following elements
  4. When using the linq method, we need to consider the case that the array is nil and the element of the corresponding group or join is nil

 

Posted by boblang on Thu, 05 May 2022 03:19:39 +0300