aggregate.go 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. package help
  2. // Aggregate applies an accumulator function over a sequence.
  3. //
  4. // Aggregate method makes it simple to perform a calculation over a sequence of
  5. // values. This method works by calling f() one time for each element in source
  6. // except the first one. Each time f() is called, Aggregate passes both the
  7. // element from the sequence and an aggregated value (as the first argument to
  8. // f()). The first element of source is used as the initial aggregate value. The
  9. // result of f() replaces the previous aggregated value.
  10. //
  11. // Aggregate returns the final result of f().
  12. func (q Query) Aggregate(f func(interface{}, interface{}) interface{}) interface{} {
  13. next := q.Iterate()
  14. result, any := next()
  15. if !any {
  16. return nil
  17. }
  18. for current, ok := next(); ok; current, ok = next() {
  19. result = f(result, current)
  20. }
  21. return result
  22. }
  23. // AggregateT is the typed version of Aggregate.
  24. //
  25. // - f is of type: func(TSource, TSource) TSource
  26. //
  27. // NOTE: Aggregate has better performance than AggregateT.
  28. func (q Query) AggregateT(f interface{}) interface{} {
  29. fGenericFunc, err := newGenericFunc(
  30. "AggregateT", "f", f,
  31. simpleParamValidator(newElemTypeSlice(new(genericType), new(genericType)), newElemTypeSlice(new(genericType))),
  32. )
  33. if err != nil {
  34. panic(err)
  35. }
  36. fFunc := func(result interface{}, current interface{}) interface{} {
  37. return fGenericFunc.Call(result, current)
  38. }
  39. return q.Aggregate(fFunc)
  40. }
  41. // AggregateWithSeed applies an accumulator function over a sequence. The
  42. // specified seed value is used as the initial accumulator value.
  43. //
  44. // Aggregate method makes it simple to perform a calculation over a sequence of
  45. // values. This method works by calling f() one time for each element in source
  46. // except the first one. Each time f() is called, Aggregate passes both the
  47. // element from the sequence and an aggregated value (as the first argument to
  48. // f()). The value of the seed parameter is used as the initial aggregate value.
  49. // The result of f() replaces the previous aggregated value.
  50. //
  51. // Aggregate returns the final result of f().
  52. func (q Query) AggregateWithSeed(seed interface{},
  53. f func(interface{}, interface{}) interface{}) interface{} {
  54. next := q.Iterate()
  55. result := seed
  56. for current, ok := next(); ok; current, ok = next() {
  57. result = f(result, current)
  58. }
  59. return result
  60. }
  61. // AggregateWithSeedT is the typed version of AggregateWithSeed.
  62. //
  63. // - f is of type "func(TAccumulate, TSource) TAccumulate"
  64. //
  65. // NOTE: AggregateWithSeed has better performance than
  66. // AggregateWithSeedT.
  67. func (q Query) AggregateWithSeedT(seed interface{},
  68. f interface{}) interface{} {
  69. fGenericFunc, err := newGenericFunc(
  70. "AggregateWithSeed", "f", f,
  71. simpleParamValidator(newElemTypeSlice(new(genericType), new(genericType)), newElemTypeSlice(new(genericType))),
  72. )
  73. if err != nil {
  74. panic(err)
  75. }
  76. fFunc := func(result interface{}, current interface{}) interface{} {
  77. return fGenericFunc.Call(result, current)
  78. }
  79. return q.AggregateWithSeed(seed, fFunc)
  80. }
  81. // AggregateWithSeedBy applies an accumulator function over a sequence. The
  82. // specified seed value is used as the initial accumulator value, and the
  83. // specified function is used to select the result value.
  84. //
  85. // Aggregate method makes it simple to perform a calculation over a sequence of
  86. // values. This method works by calling f() one time for each element in source.
  87. // Each time func is called, Aggregate passes both the element from the sequence
  88. // and an aggregated value (as the first argument to func). The value of the
  89. // seed parameter is used as the initial aggregate value. The result of func
  90. // replaces the previous aggregated value.
  91. //
  92. // The final result of func is passed to resultSelector to obtain the final
  93. // result of Aggregate.
  94. func (q Query) AggregateWithSeedBy(seed interface{},
  95. f func(interface{}, interface{}) interface{},
  96. resultSelector func(interface{}) interface{}) interface{} {
  97. next := q.Iterate()
  98. result := seed
  99. for current, ok := next(); ok; current, ok = next() {
  100. result = f(result, current)
  101. }
  102. return resultSelector(result)
  103. }
  104. // AggregateWithSeedByT is the typed version of AggregateWithSeedBy.
  105. //
  106. // - f is of type "func(TAccumulate, TSource) TAccumulate"
  107. // - resultSelectorFn is of type "func(TAccumulate) TResult"
  108. //
  109. // NOTE: AggregateWithSeedBy has better performance than
  110. // AggregateWithSeedByT.
  111. func (q Query) AggregateWithSeedByT(seed interface{},
  112. f interface{},
  113. resultSelectorFn interface{}) interface{} {
  114. fGenericFunc, err := newGenericFunc(
  115. "AggregateWithSeedByT", "f", f,
  116. simpleParamValidator(newElemTypeSlice(new(genericType), new(genericType)), newElemTypeSlice(new(genericType))),
  117. )
  118. if err != nil {
  119. panic(err)
  120. }
  121. fFunc := func(result interface{}, current interface{}) interface{} {
  122. return fGenericFunc.Call(result, current)
  123. }
  124. resultSelectorGenericFunc, err := newGenericFunc(
  125. "AggregateWithSeedByT", "resultSelectorFn", resultSelectorFn,
  126. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  127. )
  128. if err != nil {
  129. panic(err)
  130. }
  131. resultSelectorFunc := func(result interface{}) interface{} {
  132. return resultSelectorGenericFunc.Call(result)
  133. }
  134. return q.AggregateWithSeedBy(seed, fFunc, resultSelectorFunc)
  135. }