except.go 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879
  1. package help
  2. // Except produces the set difference of two sequences. The set difference is
  3. // the members of the first sequence that don't appear in the second sequence.
  4. func (q Query) Except(q2 Query) Query {
  5. return Query{
  6. Iterate: func() Iterator {
  7. next := q.Iterate()
  8. next2 := q2.Iterate()
  9. set := make(map[interface{}]bool)
  10. for i, ok := next2(); ok; i, ok = next2() {
  11. set[i] = true
  12. }
  13. return func() (item interface{}, ok bool) {
  14. for item, ok = next(); ok; item, ok = next() {
  15. if _, has := set[item]; !has {
  16. return
  17. }
  18. }
  19. return
  20. }
  21. },
  22. }
  23. }
  24. // ExceptBy invokes a transform function on each element of a collection and
  25. // produces the set difference of two sequences. The set difference is the
  26. // members of the first sequence that don't appear in the second sequence.
  27. func (q Query) ExceptBy(q2 Query,
  28. selector func(interface{}) interface{}) Query {
  29. return Query{
  30. Iterate: func() Iterator {
  31. next := q.Iterate()
  32. next2 := q2.Iterate()
  33. set := make(map[interface{}]bool)
  34. for i, ok := next2(); ok; i, ok = next2() {
  35. s := selector(i)
  36. set[s] = true
  37. }
  38. return func() (item interface{}, ok bool) {
  39. for item, ok = next(); ok; item, ok = next() {
  40. s := selector(item)
  41. if _, has := set[s]; !has {
  42. return
  43. }
  44. }
  45. return
  46. }
  47. },
  48. }
  49. }
  50. // ExceptByT is the typed version of ExceptBy.
  51. //
  52. // - selectorFn is of type "func(TSource) TSource"
  53. //
  54. // NOTE: ExceptBy has better performance than ExceptByT.
  55. func (q Query) ExceptByT(q2 Query,
  56. selectorFn interface{}) Query {
  57. selectorGenericFunc, err := newGenericFunc(
  58. "ExceptByT", "selectorFn", selectorFn,
  59. simpleParamValidator(newElemTypeSlice(new(genericType)), newElemTypeSlice(new(genericType))),
  60. )
  61. if err != nil {
  62. panic(err)
  63. }
  64. selectorFunc := func(item interface{}) interface{} {
  65. return selectorGenericFunc.Call(item)
  66. }
  67. return q.ExceptBy(q2, selectorFunc)
  68. }