1package funk
2
3type JoinIntFnc func(lx, rx []int) []int
4
5// JoinInt combines two int collections using the given join method.
6func JoinInt(larr, rarr []int, fnc JoinIntFnc) []int {
7	return fnc(larr, rarr)
8}
9
10// InnerJoinInt finds and returns matching data from two int collections.
11func InnerJoinInt(lx, rx []int) []int {
12	result := make([]int, 0, len(lx)+len(rx))
13	rhash := hashSliceInt(rx)
14	lhash := make(map[int]struct{}, len(lx))
15
16	for _, v := range lx {
17		_, ok := rhash[v]
18		_, alreadyExists := lhash[v]
19		if ok && !alreadyExists {
20			lhash[v] = struct{}{}
21			result = append(result, v)
22		}
23	}
24	return result
25}
26
27// OuterJoinInt finds and returns dissimilar data from two int collections.
28func OuterJoinInt(lx, rx []int) []int {
29	ljoin := LeftJoinInt(lx, rx)
30	rjoin := RightJoinInt(lx, rx)
31
32	result := make([]int, len(ljoin)+len(rjoin))
33	copy(result, ljoin)
34	for i, v := range rjoin {
35		result[len(ljoin)+i] = v
36	}
37	return result
38}
39
40// LeftJoinInt finds and returns dissimilar data from the first int collection (left).
41func LeftJoinInt(lx, rx []int) []int {
42	result := make([]int, 0, len(lx))
43	rhash := hashSliceInt(rx)
44
45	for _, v := range lx {
46		_, ok := rhash[v]
47		if !ok {
48			result = append(result, v)
49		}
50	}
51	return result
52}
53
54// LeftJoinInt finds and returns dissimilar data from the second int collection (right).
55func RightJoinInt(lx, rx []int) []int { return LeftJoinInt(rx, lx) }
56
57func hashSliceInt(arr []int) map[int]struct{} {
58	hash := make(map[int]struct{}, len(arr))
59	for _, i := range arr {
60		hash[i] = struct{}{}
61	}
62	return hash
63}
64
65type JoinInt32Fnc func(lx, rx []int32) []int32
66
67// JoinInt32 combines two int32 collections using the given join method.
68func JoinInt32(larr, rarr []int32, fnc JoinInt32Fnc) []int32 {
69	return fnc(larr, rarr)
70}
71
72// InnerJoinInt32 finds and returns matching data from two int32 collections.
73func InnerJoinInt32(lx, rx []int32) []int32 {
74	result := make([]int32, 0, len(lx)+len(rx))
75	rhash := hashSliceInt32(rx)
76	lhash := make(map[int32]struct{}, len(lx))
77
78	for _, v := range lx {
79		_, ok := rhash[v]
80		_, alreadyExists := lhash[v]
81		if ok && !alreadyExists {
82			lhash[v] = struct{}{}
83			result = append(result, v)
84		}
85	}
86	return result
87}
88
89// OuterJoinInt32 finds and returns dissimilar data from two int32 collections.
90func OuterJoinInt32(lx, rx []int32) []int32 {
91	ljoin := LeftJoinInt32(lx, rx)
92	rjoin := RightJoinInt32(lx, rx)
93
94	result := make([]int32, len(ljoin)+len(rjoin))
95	copy(result, ljoin)
96	for i, v := range rjoin {
97		result[len(ljoin)+i] = v
98	}
99	return result
100}
101
102// LeftJoinInt32 finds and returns dissimilar data from the first int32 collection (left).
103func LeftJoinInt32(lx, rx []int32) []int32 {
104	result := make([]int32, 0, len(lx))
105	rhash := hashSliceInt32(rx)
106
107	for _, v := range lx {
108		_, ok := rhash[v]
109		if !ok {
110			result = append(result, v)
111		}
112	}
113	return result
114}
115
116// LeftJoinInt32 finds and returns dissimilar data from the second int32 collection (right).
117func RightJoinInt32(lx, rx []int32) []int32 { return LeftJoinInt32(rx, lx) }
118
119func hashSliceInt32(arr []int32) map[int32]struct{} {
120	hash := make(map[int32]struct{}, len(arr))
121	for _, i := range arr {
122		hash[i] = struct{}{}
123	}
124	return hash
125}
126
127type JoinInt64Fnc func(lx, rx []int64) []int64
128
129// JoinInt64 combines two int64 collections using the given join method.
130func JoinInt64(larr, rarr []int64, fnc JoinInt64Fnc) []int64 {
131	return fnc(larr, rarr)
132}
133
134// InnerJoinInt64 finds and returns matching data from two int64 collections.
135func InnerJoinInt64(lx, rx []int64) []int64 {
136	result := make([]int64, 0, len(lx)+len(rx))
137	rhash := hashSliceInt64(rx)
138	lhash := make(map[int64]struct{}, len(lx))
139
140	for _, v := range lx {
141		_, ok := rhash[v]
142		_, alreadyExists := lhash[v]
143		if ok && !alreadyExists {
144			lhash[v] = struct{}{}
145			result = append(result, v)
146		}
147	}
148	return result
149}
150
151// OuterJoinInt64 finds and returns dissimilar data from two int64 collections.
152func OuterJoinInt64(lx, rx []int64) []int64 {
153	ljoin := LeftJoinInt64(lx, rx)
154	rjoin := RightJoinInt64(lx, rx)
155
156	result := make([]int64, len(ljoin)+len(rjoin))
157	copy(result, ljoin)
158	for i, v := range rjoin {
159		result[len(ljoin)+i] = v
160	}
161	return result
162}
163
164// LeftJoinInt64 finds and returns dissimilar data from the first int64 collection (left).
165func LeftJoinInt64(lx, rx []int64) []int64 {
166	result := make([]int64, 0, len(lx))
167	rhash := hashSliceInt64(rx)
168
169	for _, v := range lx {
170		_, ok := rhash[v]
171		if !ok {
172			result = append(result, v)
173		}
174	}
175	return result
176}
177
178// LeftJoinInt64 finds and returns dissimilar data from the second int64 collection (right).
179func RightJoinInt64(lx, rx []int64) []int64 { return LeftJoinInt64(rx, lx) }
180
181func hashSliceInt64(arr []int64) map[int64]struct{} {
182	hash := make(map[int64]struct{}, len(arr))
183	for _, i := range arr {
184		hash[i] = struct{}{}
185	}
186	return hash
187}
188
189type JoinStringFnc func(lx, rx []string) []string
190
191// JoinString combines two string collections using the given join method.
192func JoinString(larr, rarr []string, fnc JoinStringFnc) []string {
193	return fnc(larr, rarr)
194}
195
196// InnerJoinString finds and returns matching data from two string collections.
197func InnerJoinString(lx, rx []string) []string {
198	result := make([]string, 0, len(lx)+len(rx))
199	rhash := hashSliceString(rx)
200	lhash := make(map[string]struct{}, len(lx))
201
202	for _, v := range lx {
203		_, ok := rhash[v]
204		_, alreadyExists := lhash[v]
205		if ok && !alreadyExists {
206			lhash[v] = struct{}{}
207			result = append(result, v)
208		}
209	}
210	return result
211}
212
213// OuterJoinString finds and returns dissimilar data from two string collections.
214func OuterJoinString(lx, rx []string) []string {
215	ljoin := LeftJoinString(lx, rx)
216	rjoin := RightJoinString(lx, rx)
217
218	result := make([]string, len(ljoin)+len(rjoin))
219	copy(result, ljoin)
220	for i, v := range rjoin {
221		result[len(ljoin)+i] = v
222	}
223	return result
224}
225
226// LeftJoinString finds and returns dissimilar data from the first string collection (left).
227func LeftJoinString(lx, rx []string) []string {
228	result := make([]string, 0, len(lx))
229	rhash := hashSliceString(rx)
230
231	for _, v := range lx {
232		_, ok := rhash[v]
233		if !ok {
234			result = append(result, v)
235		}
236	}
237	return result
238}
239
240// LeftJoinString finds and returns dissimilar data from the second string collection (right).
241func RightJoinString(lx, rx []string) []string { return LeftJoinString(rx, lx) }
242
243func hashSliceString(arr []string) map[string]struct{} {
244	hash := make(map[string]struct{}, len(arr))
245	for _, i := range arr {
246		hash[i] = struct{}{}
247	}
248	return hash
249}
250
251type JoinFloat32Fnc func(lx, rx []float32) []float32
252
253// JoinFloat32 combines two float32 collections using the given join method.
254func JoinFloat32(larr, rarr []float32, fnc JoinFloat32Fnc) []float32 {
255	return fnc(larr, rarr)
256}
257
258// InnerJoinFloat32 finds and returns matching data from two float32 collections.
259func InnerJoinFloat32(lx, rx []float32) []float32 {
260	result := make([]float32, 0, len(lx)+len(rx))
261	rhash := hashSliceFloat32(rx)
262	lhash := make(map[float32]struct{}, len(lx))
263
264	for _, v := range lx {
265		_, ok := rhash[v]
266		_, alreadyExists := lhash[v]
267		if ok && !alreadyExists {
268			lhash[v] = struct{}{}
269			result = append(result, v)
270		}
271	}
272	return result
273}
274
275// OuterJoinFloat32 finds and returns dissimilar data from two float32 collections.
276func OuterJoinFloat32(lx, rx []float32) []float32 {
277	ljoin := LeftJoinFloat32(lx, rx)
278	rjoin := RightJoinFloat32(lx, rx)
279
280	result := make([]float32, len(ljoin)+len(rjoin))
281	copy(result, ljoin)
282	for i, v := range rjoin {
283		result[len(ljoin)+i] = v
284	}
285	return result
286}
287
288// LeftJoinFloat32 finds and returns dissimilar data from the first float32 collection (left).
289func LeftJoinFloat32(lx, rx []float32) []float32 {
290	result := make([]float32, 0, len(lx))
291	rhash := hashSliceFloat32(rx)
292
293	for _, v := range lx {
294		_, ok := rhash[v]
295		if !ok {
296			result = append(result, v)
297		}
298	}
299	return result
300}
301
302// LeftJoinFloat32 finds and returns dissimilar data from the second float32 collection (right).
303func RightJoinFloat32(lx, rx []float32) []float32 { return LeftJoinFloat32(rx, lx) }
304
305func hashSliceFloat32(arr []float32) map[float32]struct{} {
306	hash := make(map[float32]struct{}, len(arr))
307	for _, i := range arr {
308		hash[i] = struct{}{}
309	}
310	return hash
311}
312
313type JoinFloat64Fnc func(lx, rx []float64) []float64
314
315// JoinFloat64 combines two float64 collections using the given join method.
316func JoinFloat64(larr, rarr []float64, fnc JoinFloat64Fnc) []float64 {
317	return fnc(larr, rarr)
318}
319
320// InnerJoinFloat64 finds and returns matching data from two float64 collections.
321func InnerJoinFloat64(lx, rx []float64) []float64 {
322	result := make([]float64, 0, len(lx)+len(rx))
323	rhash := hashSliceFloat64(rx)
324	lhash := make(map[float64]struct{}, len(lx))
325
326	for _, v := range lx {
327		_, ok := rhash[v]
328		_, alreadyExists := lhash[v]
329		if ok && !alreadyExists {
330			lhash[v] = struct{}{}
331			result = append(result, v)
332		}
333	}
334	return result
335}
336
337// OuterJoinFloat64 finds and returns dissimilar data from two float64 collections.
338func OuterJoinFloat64(lx, rx []float64) []float64 {
339	ljoin := LeftJoinFloat64(lx, rx)
340	rjoin := RightJoinFloat64(lx, rx)
341
342	result := make([]float64, len(ljoin)+len(rjoin))
343	copy(result, ljoin)
344	for i, v := range rjoin {
345		result[len(ljoin)+i] = v
346	}
347	return result
348}
349
350// LeftJoinFloat64 finds and returns dissimilar data from the first float64 collection (left).
351func LeftJoinFloat64(lx, rx []float64) []float64 {
352	result := make([]float64, 0, len(lx))
353	rhash := hashSliceFloat64(rx)
354
355	for _, v := range lx {
356		_, ok := rhash[v]
357		if !ok {
358			result = append(result, v)
359		}
360	}
361	return result
362}
363
364// LeftJoinFloat64 finds and returns dissimilar data from the second float64 collection (right).
365func RightJoinFloat64(lx, rx []float64) []float64 { return LeftJoinFloat64(rx, lx) }
366
367func hashSliceFloat64(arr []float64) map[float64]struct{} {
368	hash := make(map[float64]struct{}, len(arr))
369	for _, i := range arr {
370		hash[i] = struct{}{}
371	}
372	return hash
373}
374