-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathfuncs_set_operation.go
115 lines (105 loc) · 2.96 KB
/
funcs_set_operation.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package handy
import (
"github.com/hsldymq/goiter"
"iter"
)
func union[T any](e1, e2 Iterable[T]) Enumerable[T] {
return distinct[T](NewEnumerator(goiter.Concat(e1.Iter(), e2.Iter())))
}
func unionBy[T any](e1, e2 Iterable[T], keySelector func(T) any) Enumerable[T] {
return distinctBy(NewEnumerator(goiter.Concat(e1.Iter(), e2.Iter())), keySelector)
}
func intersect[T any](e1, e2 Iterable[T]) Enumerable[T] {
typeComparable := isTypeComparable[T]()
_, comparableImpl := any(zVal[T]()).(Comparable)
if comparableImpl {
return intersectBy(e1, e2, func(v T) any { return any(v).(Comparable).ComparingKey() })
} else if typeComparable {
return intersectBy(e1, e2, func(v T) any { return v })
} else {
return NewEnumerator(goiter.Empty[T]())
}
}
func intersectBy[T any](e1, e2 Iterable[T], keySelector func(T) any) Enumerable[T] {
seq := func(yield func(T) bool) {
e2Keys := map[any]bool{}
next2, stop2 := iter.Pull(e2.Iter())
defer stop2()
for {
v, ok := next2()
if !ok {
break
}
k := keySelector(v)
e2Keys[k] = true
}
e1Keys := map[any]bool{}
next1, stop1 := iter.Pull(e1.Iter())
defer stop1()
for {
v, ok := next1()
if !ok {
return
}
k := keySelector(v)
if !e2Keys[k] {
continue
}
if e1Keys[k] {
continue
}
e1Keys[k] = true
if !yield(v) {
return
}
}
}
return NewEnumerator(seq)
}
func except[T any](e1, e2 Iterable[T]) Enumerable[T] {
typeComparable := isTypeComparable[T]()
_, comparableImpl := any(zVal[T]()).(Comparable)
if comparableImpl {
return exceptBy(e1, e2, func(v T) any { return any(v).(Comparable).ComparingKey() })
} else if typeComparable {
return exceptBy(e1, e2, func(v T) any { return v })
} else {
return NewEnumerator(e1.Iter())
}
}
func exceptBy[T any](e1, e2 Iterable[T], keySelector func(T) any) Enumerable[T] {
seq := func(yield func(T) bool) {
e2Keys := map[any]bool{}
next2, stop2 := iter.Pull(e2.Iter())
defer stop2()
for {
v, ok := next2()
if !ok {
break
}
k := keySelector(v)
e2Keys[k] = true
}
e1Keys := map[any]bool{}
next1, stop1 := iter.Pull(e1.Iter())
defer stop1()
for {
v, ok := next1()
if !ok {
return
}
k := keySelector(v)
if e2Keys[k] {
continue
}
if e1Keys[k] {
continue
}
e1Keys[k] = true
if !yield(v) {
return
}
}
}
return NewEnumerator(seq)
}