generated from datumforge/go-template
-
Notifications
You must be signed in to change notification settings - Fork 5
/
sliceutil.go
185 lines (144 loc) · 3.63 KB
/
sliceutil.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
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
package sliceutil
import (
"strconv"
)
// PruneEmptyStrings from the slice
func PruneEmptyStrings(v []string) []string {
return PruneEqual(v, "")
}
// PruneEqual removes items from the slice equal to the specified value
func PruneEqual[T comparable](inputSlice []T, equalTo T) (r []T) {
for i := range inputSlice {
if inputSlice[i] != equalTo {
r = append(r, inputSlice[i])
}
}
return
}
// Dedupe removes duplicates from a slice of elements preserving the order
func Dedupe[T comparable](inputSlice []T) (result []T) {
seen := make(map[T]struct{})
for _, inputValue := range inputSlice {
if _, ok := seen[inputValue]; !ok {
seen[inputValue] = struct{}{}
result = append(result, inputValue)
}
}
return
}
// Contains if a slice contains an element
func Contains[T comparable](inputSlice []T, element T) bool {
for _, inputValue := range inputSlice {
if inputValue == element {
return true
}
}
return false
}
// ContainsItems checks if s1 contains s2
func ContainsItems[T comparable](s1 []T, s2 []T) bool {
for _, e := range s2 {
if !Contains(s1, e) {
return false
}
}
return true
}
// ToInt converts a slice of strings to a slice of ints
func ToInt(s []string) ([]int, error) {
var ns []int
for _, ss := range s {
n, err := strconv.Atoi(ss)
if err != nil {
return nil, err
}
ns = append(ns, n)
}
return ns, nil
}
// Equal checks if the items of two slices are equal respecting the order
func Equal[T comparable](s1, s2 []T) bool {
if len(s1) != len(s2) {
return false
}
for idx := range s1 {
if s1[idx] != s2[idx] {
return false
}
}
return true
}
// IsEmpty checks if the slice has length zero
func IsEmpty[V comparable](s []V) bool {
return len(s) == 0
}
// ElementsMatch asserts that the specified listA(array, slice...) is equal to specified
// listB(array, slice...) ignoring the order of the elements. If there are duplicate elements,
// the number of appearances of each of them in both lists should match
func ElementsMatch[V comparable](s1, s2 []V) bool {
if IsEmpty(s1) && IsEmpty(s2) {
return true
}
extraS1, extrS2 := Diff(s1, s2)
return IsEmpty(extraS1) && IsEmpty(extrS2)
}
// Diff calculates the extra elements between two sequences
func Diff[V comparable](s1, s2 []V) (extraS1, extraS2 []V) {
s1Len := len(s1)
s2Len := len(s2)
visited := make([]bool, s2Len)
for i := 0; i < s1Len; i++ {
element := s1[i]
found := false
for j := 0; j < s2Len; j++ {
if visited[j] {
continue
}
if s2[j] == element {
visited[j] = true
found = true
break
}
}
if !found {
extraS1 = append(extraS1, element)
}
}
for j := 0; j < s2Len; j++ {
if visited[j] {
continue
}
extraS2 = append(extraS2, s2[j])
}
return
}
// Merge and dedupe multiple items
func Merge[V comparable](ss ...[]V) []V {
var final []V
for _, s := range ss {
final = append(final, s...)
}
return Dedupe(final)
}
// MergeItems takes in multiple items of a comparable type and merges them into a single slice
// while removing any duplicates. It then returns the resulting slice with duplicate elements removed
func MergeItems[V comparable](items ...V) []V {
return Dedupe(items)
}
// FirstNonZero function takes a slice of comparable type inputs, and returns
// the first non-zero element in the slice along with a boolean value indicating if a non-zero element was found or not
func FirstNonZero[T comparable](inputs []T) (T, bool) {
var zero T
for _, v := range inputs {
if v != zero {
return v, true
}
}
return zero, false
}
// Clone a slice through built-in copy
func Clone[T comparable](t []T) []T {
newT := make([]T, len(t))
copy(newT, t)
return newT
}