1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110
|
package funk
import (
"fmt"
"reflect"
)
// Builder contains all tools which can be chained.
type Builder interface {
Chunk(size int) Builder
Compact() Builder
Drop(n int) Builder
Filter(predicate interface{}) Builder
Flatten() Builder
FlattenDeep() Builder
Initial() Builder
Intersect(y interface{}) Builder
Join(rarr interface{}, fnc JoinFnc) Builder
Map(mapFunc interface{}) Builder
FlatMap(mapFunc interface{}) Builder
Reverse() Builder
Shuffle() Builder
Tail() Builder
Uniq() Builder
Without(values ...interface{}) Builder
All() bool
Any() bool
Contains(elem interface{}) bool
Every(elements ...interface{}) bool
Find(predicate interface{}) interface{}
ForEach(predicate interface{})
ForEachRight(predicate interface{})
Head() interface{}
Keys() interface{}
IndexOf(elem interface{}) int
IsEmpty() bool
Last() interface{}
LastIndexOf(elem interface{}) int
NotEmpty() bool
Product() float64
Reduce(reduceFunc, acc interface{}) interface{}
Sum() float64
Type() reflect.Type
Value() interface{}
Values() interface{}
}
// Chain creates a simple new go-funk.Builder from a collection. Each method
// call generate a new builder containing the previous result.
func Chain(v interface{}) Builder {
isNotNil(v, "Chain")
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return &chainBuilder{v}
}
panic(fmt.Sprintf("Type %s is not supported by Chain", valueType.String()))
}
// LazyChain creates a lazy go-funk.Builder from a collection. Each method call
// generate a new builder containing a method generating the previous value.
// With that, all data are only generated when we call a tailling method like All or Find.
func LazyChain(v interface{}) Builder {
isNotNil(v, "LazyChain")
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return &lazyBuilder{func() interface{} { return v }}
}
panic(fmt.Sprintf("Type %s is not supported by LazyChain", valueType.String()))
}
// LazyChainWith creates a lazy go-funk.Builder from a generator. Like LazyChain, each
// method call generate a new builder containing a method generating the previous value.
// But, instead of using a collection, it takes a generator which can generate values.
// With LazyChainWith, to can create a generic pipeline of collection transformation and,
// throw the generator, sending different collection.
func LazyChainWith(generator func() interface{}) Builder {
isNotNil(generator, "LazyChainWith")
return &lazyBuilder{func() interface{} {
isNotNil(generator, "LazyChainWith")
v := generator()
valueType := reflect.TypeOf(v)
if isValidBuilderEntry(valueType) ||
(valueType.Kind() == reflect.Ptr && isValidBuilderEntry(valueType.Elem())) {
return v
}
panic(fmt.Sprintf("Type %s is not supported by LazyChainWith generator", valueType.String()))
}}
}
func isNotNil(v interface{}, from string) {
if v == nil {
panic(fmt.Sprintf("nil value is not supported by %s", from))
}
}
func isValidBuilderEntry(valueType reflect.Type) bool {
return valueType.Kind() == reflect.Slice || valueType.Kind() == reflect.Array ||
valueType.Kind() == reflect.Map ||
valueType.Kind() == reflect.String
}
|