gitee.com/quant1x/gox@v1.21.2/util/lambda/array.go (about)

     1  package lambda
     2  
     3  import (
     4  	"errors"
     5  	"fmt"
     6  	"reflect"
     7  	"strings"
     8  )
     9  
    10  // make Array from source(TIn[] type)
    11  // source support array or slice type
    12  func LambdaArray(source interface{}) Array {
    13  	t := reflect.TypeOf(source)
    14  	arr := _array{source, t, t.Elem(), reflect.ValueOf(source)}
    15  	if !arr.IsSlice() {
    16  		err := fmt.Errorf("source type is %s, not array ", arr.arrayType.Kind())
    17  		panic(err)
    18  	}
    19  	return &arr
    20  }
    21  
    22  type Array interface {
    23  
    24  	// return true when obj is slice
    25  	IsSlice() bool
    26  
    27  	// array join into string
    28  	// eg
    29  	// JoinOptions.express func(u user) string {return u.name }
    30  	// JoinOptions.Symbol default `,`
    31  	Join(options JoinOptions) string
    32  
    33  	// array filter
    34  	// eg: arr.Filter(func(ele int) bool{ return ele>10})
    35  	Filter(express interface{}) Array
    36  
    37  	// sort by quick
    38  	// eg
    39  	Sort(express interface{}) Array
    40  
    41  	// sort by quick multithreading
    42  	SortMT(express interface{}) Array
    43  
    44  	// map to new array
    45  	// express func(el T) T{ return T }
    46  	Map(express interface{}) Array
    47  
    48  	// append element
    49  	Append(elements ...interface{}) Array
    50  
    51  	// maximum of array
    52  	// express eg: express func(ele TIn) TOut{ return TOut },TOut must be number Type or Compare
    53  	Max(express interface{}) interface{}
    54  
    55  	// minimum of array
    56  	// express eg: express func(ele TIn) TOut{ return TOut },TOut must be number Type or Compare
    57  	Min(express interface{}) interface{}
    58  
    59  	// Determines whether the Array contains any elements
    60  	Any(express interface{}) bool
    61  
    62  	// Determines whether the condition is satisfied for all elements in the Array
    63  	All(express interface{}) bool
    64  
    65  	// Returns a number indicating how many elements in the specified Array satisfy the condition
    66  	Count(express interface{}) int
    67  
    68  	// Returns the first element of an Array that satisfies the condition
    69  	First(express interface{}) (interface{}, error)
    70  
    71  	// Returns the last element of an Array that satisfies the condition
    72  	Last(express interface{}) (interface{}, error)
    73  
    74  	// Returns the zero based index of the first occurrence in an Array
    75  	Index(i int) (interface{}, error)
    76  
    77  	// skip and Returns the elements
    78  	Take(skip, count int) Array
    79  
    80  	// sum of the values returned by the expression
    81  	Sum(express interface{}) interface{}
    82  
    83  	// average of the values returned by the expression
    84  	Average(express interface{}) float64
    85  
    86  	// Determines whether the array contains the specified element
    87  	// number type use default comparator
    88  	// other type can implements Compare
    89  	Contains(express interface{}) bool
    90  
    91  	// array or slice pointer
    92  	// Array.Pointer().([]T or [n]T)
    93  	Pointer() interface{}
    94  }
    95  
    96  func innerLambdaArray(value reflect.Value) Array {
    97  	t := value.Type()
    98  	arr := _array{value, t, t.Elem(), value}
    99  	return &arr
   100  }
   101  
   102  type _array struct {
   103  
   104  	// source array
   105  	source interface{}
   106  	// array type
   107  	arrayType reflect.Type
   108  	// element type
   109  	elementType reflect.Type
   110  	// value type
   111  	value reflect.Value
   112  }
   113  
   114  func (p *_array) Contains(express interface{}) bool {
   115  	sz := p.Len()
   116  	if express == nil {
   117  		panic("express is null")
   118  	}
   119  	if t := reflect.TypeOf(express); t.Kind() == reflect.Func {
   120  		expType := reflect.TypeOf(express)
   121  		checkExpress(expType, []reflect.Type{p.elementType}, []reflect.Type{reflect.TypeOf(true)})
   122  		fn := reflect.ValueOf(express)
   123  		for i := 0; i < sz; i++ {
   124  			ret := fn.Call([]reflect.Value{p.value.Index(i)})
   125  			if ret[0].Interface().(bool) {
   126  				return true
   127  			}
   128  		}
   129  	} else if tor, err := BasicComparator(express); err == nil {
   130  		for i := 0; i < sz; i++ {
   131  			if tor.CompareTo(p.value.Index(i).Interface()) == 0 {
   132  				return true
   133  			}
   134  		}
   135  	} else if eq, ok := express.(Equal); ok {
   136  		for i := 0; i < sz; i++ {
   137  			if eq.Equals(p.value.Index(i).Interface()) {
   138  				return true
   139  			}
   140  		}
   141  	} else {
   142  		panic("unknown type " + t.String())
   143  	}
   144  	return false
   145  }
   146  
   147  func (p *_array) Average(express interface{}) float64 {
   148  	length := p.Len()
   149  	if length == 0 {
   150  		return float64(0)
   151  	}
   152  	sum := p.Sum(express)
   153  
   154  	switch sum.(type) {
   155  	case int:
   156  		return float64(sum.(int)) / float64(length)
   157  	case uint8:
   158  		return float64(sum.(uint8)) / float64(length)
   159  	case uint16:
   160  		return float64(sum.(uint16)) / float64(length)
   161  	case uint32:
   162  		return float64(sum.(uint32)) / float64(length)
   163  	case uint64:
   164  		return float64(sum.(uint64)) / float64(length)
   165  	case int8:
   166  		return float64(sum.(int8)) / float64(length)
   167  	case int16:
   168  		return float64(sum.(int16)) / float64(length)
   169  	case int32:
   170  		return float64(sum.(int32)) / float64(length)
   171  	case int64:
   172  		return float64(sum.(int64)) / float64(length)
   173  	case float32:
   174  		return float64(sum.(float32)) / float64(length)
   175  	case float64:
   176  		return sum.(float64) / float64(length)
   177  	default:
   178  		panic("unknown type " + reflect.TypeOf(sum).String())
   179  	}
   180  }
   181  
   182  func (p *_array) Append(elements ...interface{}) Array {
   183  	ret := LambdaArray(elements).Map(func(ele interface{}) reflect.Value {
   184  		if t := reflect.TypeOf(ele); t.Kind() != p.elementType.Kind() {
   185  			panic(fmt.Sprintf("element type[%s] is not %s.", t.String(), p.elementType.String()))
   186  		}
   187  		return reflect.ValueOf(ele)
   188  	}).Pointer().([]reflect.Value)
   189  	p.value = reflect.Append(p.value, ret...)
   190  	return p
   191  }
   192  
   193  func (p *_array) Any(express interface{}) bool {
   194  	if express == nil {
   195  		return p.Len() > 0
   196  	}
   197  	checkExpress(
   198  		reflect.TypeOf(express),
   199  		[]reflect.Type{p.elementType},
   200  		[]reflect.Type{reflect.TypeOf(true)})
   201  
   202  	length := p.Len()
   203  	fn := reflect.ValueOf(express)
   204  	for i := 0; i < length; i++ {
   205  		if fn.Call([]reflect.Value{p.value.Index(i)})[0].Interface().(bool) {
   206  			return true
   207  		}
   208  	}
   209  	return false
   210  }
   211  
   212  func (p *_array) All(express interface{}) bool {
   213  	if express == nil {
   214  		return p.Len() > 0
   215  	}
   216  	checkExpress(
   217  		reflect.TypeOf(express),
   218  		[]reflect.Type{p.elementType},
   219  		[]reflect.Type{reflect.TypeOf(true)})
   220  	length := p.Len()
   221  	fn := reflect.ValueOf(express)
   222  	for i := 0; i < length; i++ {
   223  		if !fn.Call([]reflect.Value{p.value.Index(i)})[0].Interface().(bool) {
   224  			return false
   225  		}
   226  	}
   227  	if p.Len() > 0 {
   228  		return true
   229  	} else {
   230  		return false
   231  	}
   232  }
   233  
   234  func (p *_array) Count(express interface{}) int {
   235  	if express == nil {
   236  		return p.Len()
   237  	}
   238  	checkExpress(
   239  		reflect.TypeOf(express),
   240  		[]reflect.Type{p.elementType},
   241  		[]reflect.Type{reflect.TypeOf(true)})
   242  	fn := reflect.ValueOf(express)
   243  	count := 0
   244  	p.EachV(func(v reflect.Value, _ int) {
   245  		if fn.Call([]reflect.Value{v})[0].Interface().(bool) {
   246  			count++
   247  		}
   248  	})
   249  	return count
   250  }
   251  
   252  func (p *_array) Find(express interface{}, start, step int) (interface{}, error) {
   253  	length := p.Len()
   254  	if length == 0 {
   255  		return nil, errors.New("empty array")
   256  	}
   257  
   258  	if express == nil {
   259  		return p.value.Index(0).Interface(), nil
   260  	}
   261  	checkExpress(
   262  		reflect.TypeOf(express),
   263  		[]reflect.Type{p.elementType},
   264  		[]reflect.Type{reflect.TypeOf(true)})
   265  	fn := reflect.ValueOf(express)
   266  	for i := start; i < length && i >= 0; i += step {
   267  		if ele := p.value.Index(i); fn.Call([]reflect.Value{ele})[0].Interface().(bool) {
   268  			return ele.Interface(), nil
   269  		}
   270  	}
   271  	return nil, errors.New("not found")
   272  }
   273  
   274  func (p *_array) First(express interface{}) (interface{}, error) {
   275  	return p.Find(express, 0, 1)
   276  }
   277  
   278  func (p *_array) Last(express interface{}) (interface{}, error) {
   279  	return p.Find(express, p.Len()-1, -1)
   280  }
   281  
   282  func (p *_array) Index(i int) (interface{}, error) {
   283  	if i < p.Len() {
   284  		return p.value.Index(i), nil
   285  	}
   286  	return nil, errors.New(fmt.Sprintf("%d out of range", i))
   287  }
   288  
   289  func (p *_array) Take(skip, count int) Array {
   290  	length := p.value.Len()
   291  
   292  	ret := reflect.MakeSlice(p.arrayType, 0, 0)
   293  	for i := skip; i < length; i++ {
   294  		if count > 0 {
   295  			ret = reflect.Append(ret, p.value.Index(i))
   296  			count--
   297  		}
   298  		if count == 0 {
   299  			break
   300  		}
   301  	}
   302  	return innerLambdaArray(ret)
   303  }
   304  
   305  func (p *_array) Sum(express interface{}) interface{} {
   306  
   307  	var add Add
   308  	if express == nil {
   309  		add = Adder(p.elementType)
   310  	} else {
   311  		checkExpress(
   312  			reflect.TypeOf(express),
   313  			[]reflect.Type{p.elementType},
   314  			nil)
   315  		add = Adder(reflect.TypeOf(express).Out(0))
   316  	}
   317  
   318  	length := p.Len()
   319  	if length == 0 {
   320  		return add.Value()
   321  	}
   322  
   323  	fn := reflect.ValueOf(express)
   324  
   325  	fv := func(i int) reflect.Value {
   326  		v := p.value.Index(i)
   327  		if express == nil {
   328  			return v
   329  		}
   330  		return fn.Call([]reflect.Value{v})[0]
   331  	}
   332  
   333  	for i := 0; i < length; i++ {
   334  		add.Add(fv(i))
   335  	}
   336  	return add.Value()
   337  }
   338  
   339  func (p *_array) Pointer() interface{} {
   340  	return p.value.Interface()
   341  }
   342  
   343  func (p *_array) IsSlice() bool {
   344  	return p.arrayType.Kind() == reflect.Slice || p.arrayType.Kind() == reflect.Array
   345  }
   346  
   347  func (p *_array) Len() int {
   348  	return p.value.Len()
   349  }
   350  
   351  // check the function express
   352  // exp the express function type
   353  // in express function parameter types
   354  // out express function return types
   355  func checkExpress(exp reflect.Type, in []reflect.Type, out []reflect.Type) {
   356  	if exp.Kind() != reflect.Func {
   357  		panic("express is not a func express")
   358  	}
   359  	// check in
   360  	numIn := exp.NumIn()
   361  	lenIn := len(in)
   362  	if numIn != lenIn {
   363  		panic(fmt.Errorf("lambda express parameter count must be %d", lenIn))
   364  	}
   365  	for i := 0; i < lenIn; i++ {
   366  		if in[i].Kind() != exp.In(i).Kind() {
   367  			panic(fmt.Errorf("lambda express the %d'th parameter Type must be %s,not %s,func=%s",
   368  				i, exp.In(i).String(), in[i].String(), exp.String()))
   369  		}
   370  	}
   371  	if out == nil {
   372  		return
   373  	}
   374  	// check output
   375  	numOut := exp.NumOut()
   376  	lenOut := len(out)
   377  	if numOut != lenOut {
   378  		panic(fmt.Errorf("lambda express return Types count must be %d", lenOut))
   379  	}
   380  	for i := 0; i < lenOut; i++ {
   381  		if out[i].Kind() != exp.Out(i).Kind() {
   382  			panic(fmt.Errorf("lambda express the %d'th return Type must be %s", i, exp.Out(i).String()))
   383  		}
   384  	}
   385  }
   386  
   387  // check the function express
   388  func checkExpressRARTO(express interface{}, in []reflect.Type) reflect.Type {
   389  	t := reflect.TypeOf(express)
   390  	if t.NumOut() == 0 {
   391  		panic("lambda express must has only one return-value.")
   392  	}
   393  	ot := t.Out(0)
   394  	checkExpress(t, in, []reflect.Type{ot})
   395  	return ot
   396  }
   397  
   398  func (p *_array) Map(express interface{}) Array {
   399  	in := []reflect.Type{p.elementType}
   400  	ot := checkExpressRARTO(express, in)
   401  
   402  	var result reflect.Value
   403  	length := p.Len()
   404  	// slice or array
   405  	isSlice := p.arrayType.Kind() == reflect.Slice
   406  	var element reflect.Value
   407  	if isSlice {
   408  		result = reflect.MakeSlice(reflect.SliceOf(ot), p.Len(), p.Len())
   409  		element = result
   410  	} else {
   411  		result = reflect.New(reflect.ArrayOf(length, ot))
   412  		element = result.Elem()
   413  	}
   414  
   415  	funcValue := reflect.ValueOf(express)
   416  	params := []reflect.Value{reflect.ValueOf(0)}
   417  	for i := 0; i < length; i++ {
   418  		params[0] = p.value.Index(i)
   419  		trans := funcValue.Call(params)
   420  		v := element.Index(i)
   421  		v.Set(trans[0])
   422  	}
   423  
   424  	return innerLambdaArray(result)
   425  }
   426  
   427  type JoinOptions struct {
   428  	Symbol  string
   429  	express interface{}
   430  }
   431  
   432  func (p *_array) Join(option JoinOptions) string {
   433  	if option.express != nil {
   434  		return p.Map(option.express).Join(JoinOptions{Symbol: option.Symbol})
   435  	}
   436  	if p.elementType.Kind() != reflect.String {
   437  		panic("the array is not string array")
   438  	}
   439  	if option.Symbol == "" {
   440  		option.Symbol = ","
   441  	}
   442  	length := p.Len()
   443  	var build strings.Builder
   444  	for i := 0; i < length; i++ {
   445  		s := p.value.Index(i).Interface().(string)
   446  		build.WriteString(s)
   447  		if i < length-1 {
   448  			build.WriteString(option.Symbol)
   449  		}
   450  	}
   451  	return build.String()
   452  }
   453  
   454  func (p *_array) Filter(express interface{}) Array {
   455  	in := []reflect.Type{p.elementType}
   456  	ft := reflect.TypeOf(express)
   457  	ot := reflect.TypeOf(true)
   458  	checkExpress(ft, in, []reflect.Type{ot})
   459  
   460  	ret := reflect.MakeSlice(reflect.SliceOf(p.elementType), 0, 0)
   461  	funcValue := reflect.ValueOf(express)
   462  	params := []reflect.Value{reflect.ValueOf(0)}
   463  	length := p.Len()
   464  	for i := 0; i < length; i++ {
   465  		params[0] = p.value.Index(i)
   466  		trans := funcValue.Call(params)
   467  		if trans[0].Interface().(bool) {
   468  			ret = reflect.Append(ret, params[0])
   469  		}
   470  	}
   471  	return innerLambdaArray(ret)
   472  }
   473  
   474  func (p *_array) SortByBubble(express interface{}) Array {
   475  	in := []reflect.Type{p.elementType, p.elementType}
   476  	ft := reflect.TypeOf(express)
   477  	ot := reflect.TypeOf(true)
   478  	checkExpress(ft, in, []reflect.Type{ot})
   479  
   480  	length := p.Len()
   481  	v := reflect.ValueOf(0)
   482  	funcValue := reflect.ValueOf(express)
   483  	params := []reflect.Value{v, v}
   484  	for i := 0; i < length-1; i++ {
   485  		for j := 0; j < length-i-1; j++ {
   486  			params[0] = p.value.Index(j)
   487  			params[1] = p.value.Index(j + 1)
   488  			trans := funcValue.Call(params)
   489  			if !trans[0].Interface().(bool) {
   490  				temp := params[0].Interface()
   491  				p.value.Index(j).Set(params[1])
   492  				p.value.Index(j + 1).Set(reflect.ValueOf(temp))
   493  			}
   494  		}
   495  	}
   496  
   497  	return p
   498  }
   499  
   500  func (p *_array) CopyValue() reflect.Value {
   501  	var arr reflect.Value
   502  	if p.IsSlice() {
   503  		arr = reflect.MakeSlice(reflect.SliceOf(p.elementType), p.Len(), p.Len())
   504  	} else {
   505  		arr = reflect.New(reflect.ArrayOf(p.Len(), p.elementType))
   506  	}
   507  	reflect.Copy(arr, p.value)
   508  	return arr
   509  }
   510  
   511  func (p *_array) Sort(express interface{}) Array {
   512  	in := []reflect.Type{p.elementType, p.elementType}
   513  	ft := reflect.TypeOf(express)
   514  	ot := reflect.TypeOf(true)
   515  	checkExpress(ft, in, []reflect.Type{ot})
   516  
   517  	length := p.Len()
   518  	v := reflect.ValueOf(0)
   519  	funcValue := reflect.ValueOf(express)
   520  	params := []reflect.Value{v, v}
   521  
   522  	p.value = p.CopyValue()
   523  
   524  	compare := func(a reflect.Value, b int) bool {
   525  		params[0], params[1] = a, p.value.Index(b)
   526  		return funcValue.Call(params)[0].Interface().(bool)
   527  	}
   528  
   529  	var inner func(int, int)
   530  	// quick sort
   531  	inner = func(l, r int) {
   532  		if l < r {
   533  			i, j, x := l, r, p.value.Index(l)
   534  			x = reflect.ValueOf(x.Interface())
   535  			for i < j {
   536  				for i < j && compare(x, j) {
   537  					j--
   538  				}
   539  				if i < j {
   540  					p.value.Index(i).Set(p.value.Index(j))
   541  					i++
   542  				}
   543  				for i < j && !compare(x, i) {
   544  					i++
   545  				}
   546  				if i < j {
   547  					p.value.Index(j).Set(p.value.Index(i))
   548  					j--
   549  				}
   550  			}
   551  			p.value.Index(i).Set(x)
   552  			inner(l, i-1)
   553  			inner(i+1, r)
   554  		}
   555  	}
   556  	inner(0, length-1)
   557  	return p
   558  }
   559  
   560  func (p *_array) SortMT(express interface{}) Array {
   561  	in := []reflect.Type{p.elementType, p.elementType}
   562  	ft := reflect.TypeOf(express)
   563  	ot := reflect.TypeOf(true)
   564  	checkExpress(ft, in, []reflect.Type{ot})
   565  
   566  	funcValue := reflect.ValueOf(express)
   567  
   568  	compare := func(a, b reflect.Value) bool {
   569  		return funcValue.Call([]reflect.Value{a, b})[0].Interface().(bool)
   570  	}
   571  	var quick func(arr reflect.Value, ch chan reflect.Value)
   572  	quick = func(arr reflect.Value, ch chan reflect.Value) {
   573  		if arr.Len() == 1 {
   574  			ch <- arr.Index(0)
   575  			close(ch)
   576  			return
   577  		}
   578  		if arr.Len() == 0 {
   579  			close(ch)
   580  			return
   581  		}
   582  
   583  		left := reflect.MakeSlice(reflect.SliceOf(p.elementType), 0, 0)
   584  		right := reflect.MakeSlice(reflect.SliceOf(p.elementType), 0, 0)
   585  		length := arr.Len()
   586  		x := arr.Index(0)
   587  		for i := 1; i < length; i++ {
   588  			curr := arr.Index(i)
   589  			if compare(x, curr) {
   590  				left = reflect.Append(left, curr)
   591  			} else {
   592  				right = reflect.Append(right, curr)
   593  			}
   594  		}
   595  		lch := make(chan reflect.Value, left.Len())
   596  		rch := make(chan reflect.Value, right.Len())
   597  		go quick(left, lch)
   598  		go quick(right, rch)
   599  		for v := range lch {
   600  			ch <- v
   601  		}
   602  		ch <- x
   603  		for v := range rch {
   604  			ch <- v
   605  		}
   606  		close(ch)
   607  	}
   608  	ch := make(chan reflect.Value)
   609  	go quick(p.value, ch)
   610  	values := reflect.MakeSlice(reflect.SliceOf(p.elementType), 0, 0)
   611  	for v := range ch {
   612  		values = reflect.Append(values, v)
   613  	}
   614  	return innerLambdaArray(values)
   615  }
   616  
   617  func (p *_array) maxOrMin(express interface{}, isMax bool) interface{} {
   618  	if express != nil {
   619  		in := []reflect.Type{p.elementType}
   620  		ft := reflect.TypeOf(express)
   621  		ot := reflect.TypeOf(0)
   622  		checkExpress(ft, in, []reflect.Type{ot})
   623  	}
   624  	var m reflect.Value
   625  	var mc interface{}
   626  
   627  	funcValue := reflect.ValueOf(express)
   628  	f := func(value reflect.Value) interface{} {
   629  		if express == nil {
   630  			return value.Interface()
   631  		}
   632  		return funcValue.Call([]reflect.Value{value})[0].Interface()
   633  	}
   634  
   635  	p.EachV(func(v reflect.Value, index int) {
   636  		vc := f(v)
   637  		if index == 0 {
   638  			m = v
   639  			mc = vc
   640  		} else {
   641  			tor, err := BasicComparator(vc)
   642  			if err != nil {
   643  				panic(err)
   644  			}
   645  			if isMax {
   646  				if tor.CompareTo(mc) > 0 {
   647  					m = v
   648  					mc = vc
   649  				}
   650  			} else {
   651  				if tor.CompareTo(mc) < 0 {
   652  					m = v
   653  					mc = vc
   654  				}
   655  			}
   656  		}
   657  	})
   658  	return m.Interface()
   659  }
   660  
   661  func (p *_array) Max(express interface{}) interface{} {
   662  	return p.maxOrMin(express, true)
   663  }
   664  
   665  func (p *_array) Min(express interface{}) interface{} {
   666  	return p.maxOrMin(express, false)
   667  }
   668  
   669  func (p *_array) EachV(fn func(v reflect.Value, i int)) {
   670  	if fn == nil {
   671  		return
   672  	}
   673  	length := p.Len()
   674  
   675  	for i := 0; i < length; i++ {
   676  		fn(p.value.Index(i), i)
   677  	}
   678  }