intersect.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687
  1. package help
  2. // Intersect produces the set intersection of the source collection and the
  3. // provided input collection. The intersection of two sets A and B is defined as
  4. // the set that contains all the elements of A that also appear in B, but no
  5. // other elements.
  6. func (q Query) Intersect(q2 Query) Query {
  7. return Query{
  8. Iterate: func() Iterator {
  9. next := q.Iterate()
  10. next2 := q2.Iterate()
  11. set := make(map[interface{}]bool)
  12. for item, ok := next2(); ok; item, ok = next2() {
  13. set[item] = true
  14. }
  15. return func() (item interface{}, ok bool) {
  16. for item, ok = next(); ok; item, ok = next() {
  17. if _, has := set[item]; has {
  18. delete(set, item)
  19. return
  20. }
  21. }
  22. return
  23. }
  24. },
  25. }
  26. }
  27. // IntersectBy produces the set intersection of the source collection and the
  28. // provided input collection. The intersection of two sets A and B is defined as
  29. // the set that contains all the elements of A that also appear in B, but no
  30. // other elements.
  31. //
  32. // IntersectBy invokes a transform function on each element of both collections.
  33. func (q Query) IntersectBy(q2 Query,
  34. selector func(interface{}) interface{}) Query {
  35. return Query{
  36. Iterate: func() Iterator {
  37. next := q.Iterate()
  38. next2 := q2.Iterate()
  39. set := make(map[interface{}]bool)
  40. for item, ok := next2(); ok; item, ok = next2() {
  41. s := selector(item)
  42. set[s] = true
  43. }
  44. return func() (item interface{}, ok bool) {
  45. for item, ok = next(); ok; item, ok = next() {
  46. s := selector(item)
  47. if _, has := set[s]; has {
  48. delete(set, s)
  49. return
  50. }
  51. }
  52. return
  53. }
  54. },
  55. }
  56. }
  57. // IntersectByT is the typed version of IntersectBy.
  58. //
  59. // - selectorFn is of type "func(TSource) TSource"
  60. //
  61. // NOTE: IntersectBy has better performance than IntersectByT.
  62. func (q Query) IntersectByT(q2 Query,
  63. selectorFn interface{}) Query {
  64. selectorGenericFunc, err := newGenericFunc(
  65. "IntersectByT", "selectorFn", selectorFn,
  66. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  67. )
  68. if err != nil {
  69. panic(err)
  70. }
  71. selectorFunc := func(item interface{}) interface{} {
  72. return selectorGenericFunc.Call(item)
  73. }
  74. return q.IntersectBy(q2, selectorFunc)
  75. }