feat(Go-Tool):2020/11/12:新增linq包使用示例(未完成)
This commit is contained in:
+394
@@ -0,0 +1,394 @@
|
||||
package linq
|
||||
|
||||
import (
|
||||
"math"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
// All determines whether all elements of a collection satisfy a condition.
|
||||
func (q Query) All(predicate func(interface{}) bool) bool {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if !predicate(item) {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
// Any determines whether any element of a collection exists.
|
||||
func (q Query) Any() bool {
|
||||
_, ok := q.Iterate()()
|
||||
return ok
|
||||
}
|
||||
|
||||
// AnyWith determines whether any element of a collection satisfies a condition.
|
||||
func (q Query) AnyWith(predicate func(interface{}) bool) bool {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if predicate(item) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Average computes the average of a collection of numeric values.
|
||||
func (q Query) Average() (r float64) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return math.NaN()
|
||||
}
|
||||
|
||||
n := 1
|
||||
switch item.(type) {
|
||||
case int, int8, int16, int32, int64:
|
||||
conv := getIntConverter(item)
|
||||
sum := conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
sum += conv(item)
|
||||
n++
|
||||
}
|
||||
|
||||
r = float64(sum)
|
||||
case uint, uint8, uint16, uint32, uint64:
|
||||
conv := getUIntConverter(item)
|
||||
sum := conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
sum += conv(item)
|
||||
n++
|
||||
}
|
||||
|
||||
r = float64(sum)
|
||||
default:
|
||||
conv := getFloatConverter(item)
|
||||
r = conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
r += conv(item)
|
||||
n++
|
||||
}
|
||||
}
|
||||
|
||||
return r / float64(n)
|
||||
}
|
||||
|
||||
// Contains determines whether a collection contains a specified element.
|
||||
func (q Query) Contains(value interface{}) bool {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if item == value {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// Count returns the number of elements in a collection.
|
||||
func (q Query) Count() (r int) {
|
||||
next := q.Iterate()
|
||||
|
||||
for _, ok := next(); ok; _, ok = next() {
|
||||
r++
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// CountWith returns a number that represents how many elements
|
||||
// in the specified collection satisfy a condition.
|
||||
func (q Query) CountWith(predicate func(interface{}) bool) (r int) {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if predicate(item) {
|
||||
r++
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// First returns the first element of a collection.
|
||||
func (q Query) First() interface{} {
|
||||
item, _ := q.Iterate()()
|
||||
return item
|
||||
}
|
||||
|
||||
// FirstWith returns the first element of a collection that satisfies
|
||||
// a specified condition.
|
||||
func (q Query) FirstWith(predicate func(interface{}) bool) interface{} {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if predicate(item) {
|
||||
return item
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// Last returns the last element of a collection.
|
||||
func (q Query) Last() (r interface{}) {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
r = item
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// LastWith returns the last element of a collection that satisfies
|
||||
// a specified condition.
|
||||
func (q Query) LastWith(predicate func(interface{}) bool) (r interface{}) {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if predicate(item) {
|
||||
r = item
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Max returns the maximum value in a collection of values.
|
||||
func (q Query) Max() (r interface{}) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
compare := getComparer(item)
|
||||
r = item
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if compare(item, r) > 0 {
|
||||
r = item
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Min returns the minimum value in a collection of values.
|
||||
func (q Query) Min() (r interface{}) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
compare := getComparer(item)
|
||||
r = item
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if compare(item, r) < 0 {
|
||||
r = item
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Results iterates over a collection and returnes slice of interfaces
|
||||
func (q Query) Results() (r []interface{}) {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
r = append(r, item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// SequenceEqual determines whether two collections are equal.
|
||||
func (q Query) SequenceEqual(q2 Query) bool {
|
||||
next := q.Iterate()
|
||||
next2 := q2.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
item2, ok2 := next2()
|
||||
if !ok2 || item != item2 {
|
||||
return false
|
||||
}
|
||||
}
|
||||
|
||||
_, ok2 := next2()
|
||||
return !ok2
|
||||
}
|
||||
|
||||
// Single returns the only element of a collection, and nil
|
||||
// if there is not exactly one element in the collection.
|
||||
func (q Query) Single() interface{} {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
_, ok = next()
|
||||
if ok {
|
||||
return nil
|
||||
}
|
||||
|
||||
return item
|
||||
}
|
||||
|
||||
// SingleWith returns the only element of a collection that satisfies
|
||||
// a specified condition, and nil if more than one such element exists.
|
||||
func (q Query) SingleWith(predicate func(interface{}) bool) (r interface{}) {
|
||||
next := q.Iterate()
|
||||
found := false
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
if predicate(item) {
|
||||
if found {
|
||||
return nil
|
||||
}
|
||||
|
||||
found = true
|
||||
r = item
|
||||
}
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (q Query) SumInts() (r int64) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
conv := getIntConverter(item)
|
||||
r = conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
r += conv(item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (q Query) SumUInts() (r uint64) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
conv := getUIntConverter(item)
|
||||
r = conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
r += conv(item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (q Query) SumFloats() (r float64) {
|
||||
next := q.Iterate()
|
||||
item, ok := next()
|
||||
if !ok {
|
||||
return 0
|
||||
}
|
||||
|
||||
conv := getFloatConverter(item)
|
||||
r = conv(item)
|
||||
|
||||
for item, ok = next(); ok; item, ok = next() {
|
||||
r += conv(item)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// ToChannel iterates over a collection and outputs each element
|
||||
// to a channel, then closes it.
|
||||
func (q Query) ToChannel(result chan<- interface{}) {
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
result <- item
|
||||
}
|
||||
|
||||
close(result)
|
||||
}
|
||||
|
||||
// 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.
|
||||
func (q Query) ToMap(result interface{}) {
|
||||
q.ToMapBy(
|
||||
result,
|
||||
func(i interface{}) interface{} {
|
||||
return i.(KeyValue).Key
|
||||
},
|
||||
func(i interface{}) interface{} {
|
||||
return i.(KeyValue).Value
|
||||
})
|
||||
}
|
||||
|
||||
// ToMapBy iterates over a collection and populates 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.
|
||||
func (q Query) ToMapBy(
|
||||
result interface{},
|
||||
keySelector func(interface{}) interface{},
|
||||
valueSelector func(interface{}) interface{},
|
||||
) {
|
||||
res := reflect.ValueOf(result)
|
||||
m := reflect.Indirect(res)
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
key := reflect.ValueOf(keySelector(item))
|
||||
value := reflect.ValueOf(valueSelector(item))
|
||||
|
||||
m.SetMapIndex(key, value)
|
||||
}
|
||||
|
||||
res.Elem().Set(m)
|
||||
}
|
||||
|
||||
// ToSlice iterates over a collection and populates result slice with elements.
|
||||
// Collection elements must be assignable to the slice's element type.
|
||||
func (q Query) ToSlice(result interface{}) {
|
||||
res := reflect.ValueOf(result)
|
||||
slice := reflect.Indirect(res)
|
||||
next := q.Iterate()
|
||||
|
||||
for item, ok := next(); ok; item, ok = next() {
|
||||
slice = reflect.Append(slice, reflect.ValueOf(item))
|
||||
}
|
||||
|
||||
res.Elem().Set(slice)
|
||||
}
|
||||
Reference in New Issue
Block a user