select.go 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. package help
  2. // Select projects each element of a collection into a new form. Returns a query
  3. // with the result of invoking the transform function on each element of
  4. // original source.
  5. //
  6. // This projection method requires the transform function, selector, to produce
  7. // one value for each value in the source collection. If selector returns a
  8. // value that is itself a collection, it is up to the consumer to traverse the
  9. // subcollections manually. In such a situation, it might be better for your
  10. // query to return a single coalesced collection of values. To achieve this, use
  11. // the SelectMany method instead of Select. Although SelectMany works similarly
  12. // to Select, it differs in that the transform function returns a collection
  13. // that is then expanded by SelectMany before it is returned.
  14. func (q Query) Select(selector func(interface{}) interface{}) Query {
  15. return Query{
  16. Iterate: func() Iterator {
  17. next := q.Iterate()
  18. return func() (item interface{}, ok bool) {
  19. var it interface{}
  20. it, ok = next()
  21. if ok {
  22. item = selector(it)
  23. }
  24. return
  25. }
  26. },
  27. }
  28. }
  29. // SelectT is the typed version of Select.
  30. // - selectorFn is of type "func(TSource)TResult"
  31. // NOTE: Select has better performance than SelectT.
  32. func (q Query) SelectT(selectorFn interface{}) Query {
  33. selectGenericFunc, err := newGenericFunc(
  34. "SelectT", "selectorFn", selectorFn,
  35. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  36. )
  37. if err != nil {
  38. panic(err)
  39. }
  40. selectorFunc := func(item interface{}) interface{} {
  41. return selectGenericFunc.Call(item)
  42. }
  43. return q.Select(selectorFunc)
  44. }
  45. // SelectIndexed projects each element of a collection into a new form by
  46. // incorporating the element's index. Returns a query with the result of
  47. // invoking the transform function on each element of original source.
  48. //
  49. // The first argument to selector represents the zero-based index of that
  50. // element in the source collection. This can be useful if the elements are in a
  51. // known order and you want to do something with an element at a particular
  52. // index, for example. It can also be useful if you want to retrieve the index
  53. // of one or more elements. The second argument to selector represents the
  54. // element to process.
  55. //
  56. // This projection method requires the transform function, selector, to produce
  57. // one value for each value in the source collection. If selector returns a
  58. // value that is itself a collection, it is up to the consumer to traverse the
  59. // subcollections manually. In such a situation, it might be better for your
  60. // query to return a single coalesced collection of values. To achieve this, use
  61. // the SelectMany method instead of Select. Although SelectMany works similarly
  62. // to Select, it differs in that the transform function returns a collection
  63. // that is then expanded by SelectMany before it is returned.
  64. func (q Query) SelectIndexed(selector func(int, interface{}) interface{}) Query {
  65. return Query{
  66. Iterate: func() Iterator {
  67. next := q.Iterate()
  68. index := 0
  69. return func() (item interface{}, ok bool) {
  70. var it interface{}
  71. it, ok = next()
  72. if ok {
  73. item = selector(index, it)
  74. index++
  75. }
  76. return
  77. }
  78. },
  79. }
  80. }
  81. // SelectIndexedT is the typed version of SelectIndexed.
  82. // - selectorFn is of type "func(int,TSource)TResult"
  83. // NOTE: SelectIndexed has better performance than SelectIndexedT.
  84. func (q Query) SelectIndexedT(selectorFn interface{}) Query {
  85. selectGenericFunc, err := newGenericFunc(
  86. "SelectIndexedT", "selectorFn", selectorFn,
  87. simpleParamValidator(newElemTypeSlice(new(int), new(genericType)), newElemTypeSlice(new(genericType))),
  88. )
  89. if err != nil {
  90. panic(err)
  91. }
  92. selectorFunc := func(index int, item interface{}) interface{} {
  93. return selectGenericFunc.Call(index, item)
  94. }
  95. return q.SelectIndexed(selectorFunc)
  96. }