forked from juliangruber/go-intersect
-
Notifications
You must be signed in to change notification settings - Fork 0
/
intersect.go
130 lines (106 loc) · 2.5 KB
/
intersect.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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
package intersect
import (
"reflect"
"sort"
)
// Simple has complexity: O(n^2)
func SimpleGeneric[T comparable](a []T, b []T) []T {
set := make([]T, 0)
for _, v := range a {
if containsGeneric(b, v) {
set = append(set, v)
}
}
return set
}
// Sorted has complexity: O(n * log(n)), a needs to be sorted
func SortedGeneric[T comparable](a []T, b []T) []T {
set := make([]T, 0)
for _, v := range a {
idx := sort.Search(len(b), func(i int) bool {
return b[i] == v
})
if idx < len(b) && b[idx] == v {
set = append(set, v)
}
}
return set
}
// Hash has complexity: O(n * x) where x is a factor of hash function efficiency (between 1 and 2)
func HashGeneric[T comparable](a []T, b []T) []T {
set := make([]T, 0)
hash := make(map[T]bool)
for _, v := range a {
hash[v] = true
}
for _, v := range b {
if hash[v] {
set = append(set, v)
}
}
return set
}
func containsGeneric[T comparable](b []T, e T) bool {
for _, v := range b {
if v == e {
return true
}
}
return false
}
// Deprecated: Use SimpleGeneric instead. Complexity same as SimpleGeneric.
func Simple(a interface{}, b interface{}) []interface{} {
set := make([]interface{}, 0)
av := reflect.ValueOf(a)
for i := 0; i < av.Len(); i++ {
el := av.Index(i).Interface()
if contains(b, el) {
set = append(set, el)
}
}
return set
}
// Deprecated: Use SortedGeneric instead. Complexity same as SortedGeneric.
func Sorted(a interface{}, b interface{}) []interface{} {
set := make([]interface{}, 0)
av := reflect.ValueOf(a)
bv := reflect.ValueOf(b)
for i := 0; i < av.Len(); i++ {
el := av.Index(i).Interface()
idx := sort.Search(bv.Len(), func(i int) bool {
return bv.Index(i).Interface() == el
})
if idx < bv.Len() && bv.Index(idx).Interface() == el {
set = append(set, el)
}
}
return set
}
// Deprecated: Use HashGeneric instead. Complexity same as HashGeneric.
func Hash(a interface{}, b interface{}) []interface{} {
set := make([]interface{}, 0)
hash := make(map[interface{}]bool)
av := reflect.ValueOf(a)
bv := reflect.ValueOf(b)
for i := 0; i < av.Len(); i++ {
el := av.Index(i).Interface()
hash[el] = true
}
for i := 0; i < bv.Len(); i++ {
el := bv.Index(i).Interface()
if _, found := hash[el]; found {
set = append(set, el)
}
}
return set
}
// Deprecated: Used by Simple which uses reflection.
func contains(a interface{}, e interface{}) bool {
v := reflect.ValueOf(a)
for i := 0; i < v.Len(); i++ {
if v.Index(i).Interface() == e {
return true
}
}
return false
}