1package funk
2
3import (
4	"reflect"
5)
6
7// Intersect returns the intersection between two collections.
8//
9// Deprecated: use Join(x, y, InnerJoin) instead of Intersect, InnerJoin
10// implements deduplication mechanism, so verify your code behaviour
11// before using it
12func Intersect(x interface{}, y interface{}) interface{} {
13	if !IsCollection(x) {
14		panic("First parameter must be a collection")
15	}
16	if !IsCollection(y) {
17		panic("Second parameter must be a collection")
18	}
19
20	hash := map[interface{}]struct{}{}
21
22	xValue := reflect.ValueOf(x)
23	xType := xValue.Type()
24
25	yValue := reflect.ValueOf(y)
26	yType := yValue.Type()
27
28	if NotEqual(xType, yType) {
29		panic("Parameters must have the same type")
30	}
31
32	zType := reflect.SliceOf(xType.Elem())
33	zSlice := reflect.MakeSlice(zType, 0, 0)
34
35	for i := 0; i < xValue.Len(); i++ {
36		v := xValue.Index(i).Interface()
37		hash[v] = struct{}{}
38	}
39
40	for i := 0; i < yValue.Len(); i++ {
41		v := yValue.Index(i).Interface()
42		_, ok := hash[v]
43		if ok {
44			zSlice = reflect.Append(zSlice, yValue.Index(i))
45		}
46	}
47
48	return zSlice.Interface()
49}
50
51// IntersectString returns the intersection between two collections of string.
52func IntersectString(x []string, y []string) []string {
53	if len(x) == 0 || len(y) == 0 {
54		return []string{}
55	}
56
57	set := []string{}
58	hash := map[string]struct{}{}
59
60	for _, v := range x {
61		hash[v] = struct{}{}
62	}
63
64	for _, v := range y {
65		_, ok := hash[v]
66		if ok {
67			set = append(set, v)
68		}
69	}
70
71	return set
72}
73
74// Difference returns the difference between two collections.
75func Difference(x interface{}, y interface{}) (interface{}, interface{}) {
76	if !IsCollection(x) {
77		panic("First parameter must be a collection")
78	}
79	if !IsCollection(y) {
80		panic("Second parameter must be a collection")
81	}
82
83	xValue := reflect.ValueOf(x)
84	xType := xValue.Type()
85
86	yValue := reflect.ValueOf(y)
87	yType := yValue.Type()
88
89	if NotEqual(xType, yType) {
90		panic("Parameters must have the same type")
91	}
92
93	leftType := reflect.SliceOf(xType.Elem())
94	leftSlice := reflect.MakeSlice(leftType, 0, 0)
95	rightType := reflect.SliceOf(yType.Elem())
96	rightSlice := reflect.MakeSlice(rightType, 0, 0)
97
98	for i := 0; i < xValue.Len(); i++ {
99		v := xValue.Index(i).Interface()
100		if !Contains(y, v) {
101			leftSlice = reflect.Append(leftSlice, xValue.Index(i))
102		}
103	}
104
105	for i := 0; i < yValue.Len(); i++ {
106		v := yValue.Index(i).Interface()
107		if !Contains(x, v) {
108			rightSlice = reflect.Append(rightSlice, yValue.Index(i))
109		}
110	}
111
112	return leftSlice.Interface(), rightSlice.Interface()
113}
114
115// DifferenceString returns the difference between two collections of strings.
116func DifferenceString(x []string, y []string) ([]string, []string) {
117	leftSlice := []string{}
118	rightSlice := []string{}
119
120	for _, v := range x {
121		if !ContainsString(y, v) {
122			leftSlice = append(leftSlice, v)
123		}
124	}
125
126	for _, v := range y {
127		if !ContainsString(x, v) {
128			rightSlice = append(rightSlice, v)
129		}
130	}
131
132	return leftSlice, rightSlice
133}
134
135// DifferenceInt64 returns the difference between two collections of int64s.
136func DifferenceInt64(x []int64, y []int64) ([]int64, []int64) {
137	leftSlice := []int64{}
138	rightSlice := []int64{}
139
140	for _, v := range x {
141		if !ContainsInt64(y, v) {
142			leftSlice = append(leftSlice, v)
143		}
144	}
145
146	for _, v := range y {
147		if !ContainsInt64(x, v) {
148			rightSlice = append(rightSlice, v)
149		}
150	}
151
152	return leftSlice, rightSlice
153}
154
155// DifferenceInt32 returns the difference between two collections of ints32.
156func DifferenceInt32(x []int32, y []int32) ([]int32, []int32) {
157	leftSlice := []int32{}
158	rightSlice := []int32{}
159
160	for _, v := range x {
161		if !ContainsInt32(y, v) {
162			leftSlice = append(leftSlice, v)
163		}
164	}
165
166	for _, v := range y {
167		if !ContainsInt32(x, v) {
168			rightSlice = append(rightSlice, v)
169		}
170	}
171
172	return leftSlice, rightSlice
173}
174
175// DifferenceInt returns the difference between two collections of ints.
176func DifferenceInt(x []int, y []int) ([]int, []int) {
177	leftSlice := []int{}
178	rightSlice := []int{}
179
180	for _, v := range x {
181		if !ContainsInt(y, v) {
182			leftSlice = append(leftSlice, v)
183		}
184	}
185
186	for _, v := range y {
187		if !ContainsInt(x, v) {
188			rightSlice = append(rightSlice, v)
189		}
190	}
191
192	return leftSlice, rightSlice
193}
194
195// DifferenceUInt returns the difference between two collections of uints.
196func DifferenceUInt(x []uint, y []uint) ([]uint, []uint) {
197	leftSlice := []uint{}
198	rightSlice := []uint{}
199
200	for _, v := range x {
201		if !ContainsUInt(y, v) {
202			leftSlice = append(leftSlice, v)
203		}
204	}
205
206	for _, v := range y {
207		if !ContainsUInt(x, v) {
208			rightSlice = append(rightSlice, v)
209		}
210	}
211
212	return leftSlice, rightSlice
213}
214
215// DifferenceUInt32 returns the difference between two collections of uints32.
216func DifferenceUInt32(x []uint32, y []uint32) ([]uint32, []uint32) {
217	leftSlice := []uint32{}
218	rightSlice := []uint32{}
219
220	for _, v := range x {
221		if !ContainsUInt32(y, v) {
222			leftSlice = append(leftSlice, v)
223		}
224	}
225
226	for _, v := range y {
227		if !ContainsUInt32(x, v) {
228			rightSlice = append(rightSlice, v)
229		}
230	}
231
232	return leftSlice, rightSlice
233}
234
235// DifferenceUInt64 returns the difference between two collections of uints64.
236func DifferenceUInt64(x []uint64, y []uint64) ([]uint64, []uint64) {
237	leftSlice := []uint64{}
238	rightSlice := []uint64{}
239
240	for _, v := range x {
241		if !ContainsUInt64(y, v) {
242			leftSlice = append(leftSlice, v)
243		}
244	}
245
246	for _, v := range y {
247		if !ContainsUInt64(x, v) {
248			rightSlice = append(rightSlice, v)
249		}
250	}
251
252	return leftSlice, rightSlice
253}
254