distinct.go 2.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798
  1. package help
  2. // Distinct method returns distinct elements from a collection. The result is an
  3. // unordered collection that contains no duplicate values.
  4. func (q Query) Distinct() Query {
  5. return Query{
  6. Iterate: func() Iterator {
  7. next := q.Iterate()
  8. set := make(map[interface{}]bool)
  9. return func() (item interface{}, ok bool) {
  10. for item, ok = next(); ok; item, ok = next() {
  11. if _, has := set[item]; !has {
  12. set[item] = true
  13. return
  14. }
  15. }
  16. return
  17. }
  18. },
  19. }
  20. }
  21. // Distinct method returns distinct elements from a collection. The result is an
  22. // ordered collection that contains no duplicate values.
  23. //
  24. // NOTE: Distinct method on OrderedQuery type has better performance than
  25. // Distinct method on Query type.
  26. func (oq OrderedQuery) Distinct() OrderedQuery {
  27. return OrderedQuery{
  28. orders: oq.orders,
  29. Query: Query{
  30. Iterate: func() Iterator {
  31. next := oq.Iterate()
  32. var prev interface{}
  33. return func() (item interface{}, ok bool) {
  34. for item, ok = next(); ok; item, ok = next() {
  35. if item != prev {
  36. prev = item
  37. return
  38. }
  39. }
  40. return
  41. }
  42. },
  43. },
  44. }
  45. }
  46. // DistinctBy method returns distinct elements from a collection. This method
  47. // executes selector function for each element to determine a value to compare.
  48. // The result is an unordered collection that contains no duplicate values.
  49. func (q Query) DistinctBy(selector func(interface{}) interface{}) Query {
  50. return Query{
  51. Iterate: func() Iterator {
  52. next := q.Iterate()
  53. set := make(map[interface{}]bool)
  54. return func() (item interface{}, ok bool) {
  55. for item, ok = next(); ok; item, ok = next() {
  56. s := selector(item)
  57. if _, has := set[s]; !has {
  58. set[s] = true
  59. return
  60. }
  61. }
  62. return
  63. }
  64. },
  65. }
  66. }
  67. // DistinctByT is the typed version of DistinctBy.
  68. //
  69. // - selectorFn is of type "func(TSource) TSource".
  70. //
  71. // NOTE: DistinctBy has better performance than DistinctByT.
  72. func (q Query) DistinctByT(selectorFn interface{}) Query {
  73. selectorFunc, ok := selectorFn.(func(interface{}) interface{})
  74. if !ok {
  75. selectorGenericFunc, err := newGenericFunc(
  76. "DistinctByT", "selectorFn", selectorFn,
  77. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  78. )
  79. if err != nil {
  80. panic(err)
  81. }
  82. selectorFunc = func(item interface{}) interface{} {
  83. return selectorGenericFunc.Call(item)
  84. }
  85. }
  86. return q.DistinctBy(selectorFunc)
  87. }