-
Notifications
You must be signed in to change notification settings - Fork 1
/
set.go
167 lines (140 loc) · 3.47 KB
/
set.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
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
package sliset
import (
"golang.org/x/exp/slices"
)
// Contains returns the result of elem whether exists in base,
// if existed, return true, or false.
func Contains[E1 Int | Float | ~string](base []E1, elem E1) bool {
if Index(base, elem) >= 0 {
return true
}
return false
}
// Index returns the index of the first occurrence of elem in base,
// or -1 if not present.
func Index[E1 Int | Float | ~string](base []E1, elem E1) int {
return slices.Index(base, elem)
}
// Difference res = base - compared
func Difference[E1 Int | Float | ~string](base, compared []E1) []E1 {
if len(base) <= 0 {
return make([]E1, 0)
}
// 倘若 compared.len == 0, 也应当响应一个 base 的备份,而不是返回原数组
comparedSet := S2Set(compared)
newRes := make([]E1, 0)
for _, val := range base {
if comparedSet[val] {
continue
}
newRes = append(newRes, val)
}
return Uniq(newRes)
}
// Intersection res = base ∩ compared
func Intersection[E1 Int | Float | string](base, compared []E1) []E1 {
if len(base) <= 0 || len(compared) <= 0 {
return make([]E1, 0)
}
rightSet := S2Set(compared)
newRes := make([]E1, 0)
for _, val := range base {
if rightSet[val] {
newRes = append(newRes, val)
}
}
return Uniq(newRes)
}
// Union res = base U compared
func Union[E1 Int | Float | string](base, compared []E1) []E1 {
res := make([]E1, len(base)+len(compared))
i := 0
for _, val := range base {
res[i] = val
i++
}
for _, val := range compared {
res[i] = val
i++
}
return Uniq(res)
}
// Uniq remove duplicate elements from the base.
func Uniq[E1 Int | Float | ~string](base []E1) []E1 {
if len(base) <= 0 {
return make([]E1, 0)
}
res := make([]E1, 0)
cache := make(map[E1]struct{}, len(base))
for _, val := range base {
if _, ok := cache[val]; ok {
continue
}
res = append(res, val)
cache[val] = struct{}{}
}
return res
}
// Discard remove specified elem from the base.
func Discard[E1 Int | Float | string](base []E1, elem E1) []E1 {
res := make([]E1, 0)
for _, val := range base {
if val == elem {
continue
}
res = append(res, val)
}
return Uniq(res)
}
// S2Set turn slice to set. no used map[E1]struct{} to save memory because
// the bool may reduce the program's complexity.
func S2Set[E1 Int | Float | ~string](base []E1) map[E1]bool {
m := make(map[E1]bool)
for _, val := range base {
m[val] = true
}
return m
}
// S2Map turn slice to map, the key is custom by getKey()
func S2Map[E1 any, E2 comparable](base []E1, getKey func(E1) E2) map[E2]E1 {
m := make(map[E2]E1)
for i, val := range base {
m[getKey(val)] = base[i]
}
return m
}
// Deprecated: use Projection() instead
func List[E1 any, E2 any](base []E1, getValue func(E1) E2) []E2 {
return Projection(base, getValue)
}
func Projection[E1 any, E2 any](base []E1, getValue func(E1) E2) []E2 {
r := make([]E2, len(base))
for i, val := range base {
r[i] = getValue(val)
}
return r
}
func Copy[E1 Int | Float | string](base []E1) []E1 {
res := make([]E1, len(base))
for i, _ := range base {
res[i] = base[i]
}
return res
}
// IsDisJoint 判断两个集合是否包含相同元素
func IsDisJoint[E1 Int | Float | string](base, compared []E1) bool {
if len(base) <= 0 || len(compared) <= 0 {
return false
}
comparedSet := S2Set(compared)
for _, val := range base {
if comparedSet[val] {
return true
}
}
return false
}
// IsSubset Is the compared slice a sub set of base
//func IsSubset[E1 Int | Float | string](base, compared []E1) bool {
// return false
//}