take.go 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129
  1. package help
  2. // Take returns a specified number of contiguous elements from the start of a
  3. // collection.
  4. func (q Query) Take(count int) Query {
  5. return Query{
  6. Iterate: func() Iterator {
  7. next := q.Iterate()
  8. n := count
  9. return func() (item interface{}, ok bool) {
  10. if n <= 0 {
  11. return
  12. }
  13. n--
  14. return next()
  15. }
  16. },
  17. }
  18. }
  19. // TakeWhile returns elements from a collection as long as a specified condition
  20. // is true, and then skips the remaining elements.
  21. func (q Query) TakeWhile(predicate func(interface{}) bool) Query {
  22. return Query{
  23. Iterate: func() Iterator {
  24. next := q.Iterate()
  25. done := false
  26. return func() (item interface{}, ok bool) {
  27. if done {
  28. return
  29. }
  30. item, ok = next()
  31. if !ok {
  32. done = true
  33. return
  34. }
  35. if predicate(item) {
  36. return
  37. }
  38. done = true
  39. return nil, false
  40. }
  41. },
  42. }
  43. }
  44. // TakeWhileT is the typed version of TakeWhile.
  45. //
  46. // - predicateFn is of type "func(TSource)bool"
  47. //
  48. // NOTE: TakeWhile has better performance than TakeWhileT.
  49. func (q Query) TakeWhileT(predicateFn interface{}) Query {
  50. predicateGenericFunc, err := newGenericFunc(
  51. "TakeWhileT", "predicateFn", predicateFn,
  52. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(bool))),
  53. )
  54. if err != nil {
  55. panic(err)
  56. }
  57. predicateFunc := func(item interface{}) bool {
  58. return predicateGenericFunc.Call(item).(bool)
  59. }
  60. return q.TakeWhile(predicateFunc)
  61. }
  62. // TakeWhileIndexed returns elements from a collection as long as a specified
  63. // condition is true. The element's index is used in the logic of the predicate
  64. // function. The first argument of predicate represents the zero-based index of
  65. // the element within collection. The second argument represents the element to
  66. // test.
  67. func (q Query) TakeWhileIndexed(predicate func(int, interface{}) bool) Query {
  68. return Query{
  69. Iterate: func() Iterator {
  70. next := q.Iterate()
  71. done := false
  72. index := 0
  73. return func() (item interface{}, ok bool) {
  74. if done {
  75. return
  76. }
  77. item, ok = next()
  78. if !ok {
  79. done = true
  80. return
  81. }
  82. if predicate(index, item) {
  83. index++
  84. return
  85. }
  86. done = true
  87. return nil, false
  88. }
  89. },
  90. }
  91. }
  92. // TakeWhileIndexedT is the typed version of TakeWhileIndexed.
  93. //
  94. // - predicateFn is of type "func(int,TSource)bool"
  95. //
  96. // NOTE: TakeWhileIndexed has better performance than TakeWhileIndexedT.
  97. func (q Query) TakeWhileIndexedT(predicateFn interface{}) Query {
  98. whereFunc, err := newGenericFunc(
  99. "TakeWhileIndexedT", "predicateFn", predicateFn,
  100. simpleParamValidator(newElemTypeSlice(new(int), new(genericType)), newElemTypeSlice(new(bool))),
  101. )
  102. if err != nil {
  103. panic(err)
  104. }
  105. predicateFunc := func(index int, item interface{}) bool {
  106. return whereFunc.Call(index, item).(bool)
  107. }
  108. return q.TakeWhileIndexed(predicateFunc)
  109. }