-
Notifications
You must be signed in to change notification settings - Fork 247
/
sliceutils.go
138 lines (125 loc) · 3.16 KB
/
sliceutils.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
package sliceutils
import (
"github.com/pkg/errors"
"reflect"
)
// StringSlice2InterfaceSlice converts string slice to interface slice
func StringSlice2InterfaceSlice(strSlice []string) []interface{} {
ret := make([]interface{}, len(strSlice))
for i, v := range strSlice {
ret[i] = v
}
return ret
}
// InterfaceSlice2StringSlice converts interface slice to string slice
func InterfaceSlice2StringSlice(strSlice []interface{}) []string {
ret := make([]string, len(strSlice))
for i, v := range strSlice {
ret[i] = v.(string)
}
return ret
}
// Contains asserts src contains test
func Contains(src []interface{}, test interface{}) bool {
for _, item := range src {
if item == test {
return true
}
}
return false
}
// ContainsDeep asserts src contains test using reflect.DeepEqual
func ContainsDeep(src []interface{}, test interface{}) bool {
for _, item := range src {
if reflect.DeepEqual(item, test) {
return true
}
}
return false
}
// StringContains asserts src contains test
func StringContains(src []string, test string) bool {
for _, item := range src {
if item == test {
return true
}
}
return false
}
// StringFilter filters string slice by callback function fn
// If fn returns true, the item will be appended to result
func StringFilter(src []string, fn func(item string) bool) []string {
var ret []string
for _, item := range src {
if fn(item) {
ret = append(ret, item)
}
}
return ret
}
// IndexOf returns index of element in string slice data
func IndexOf(element string, data []string) int {
for k, v := range data {
if element == v {
return k
}
}
return -1 //not found.
}
// IndexOfAny returns index of element in slice data
func IndexOfAny(target interface{}, anySlice interface{}) (int, error) {
if reflect.TypeOf(anySlice).Kind() != reflect.Slice {
return -1, errors.New("not slice")
}
data := reflect.ValueOf(anySlice)
for i := 0; i < data.Len(); i++ {
elem := data.Index(i)
if elem.Interface() == target {
return i, nil
}
}
return -1, nil //not found.
}
// IsEmpty assert src is an empty slice
func IsEmpty(src interface{}) bool {
if slice, ok := TakeSliceArg(src); ok {
return slice == nil || len(slice) == 0
}
panic("not slice")
}
// TakeSliceArg https://ahmet.im/blog/golang-take-slices-of-any-type-as-input-parameter/
func TakeSliceArg(arg interface{}) (out []interface{}, ok bool) {
slice, success := takeArg(arg, reflect.Slice)
if !success {
ok = false
return
}
c := slice.Len()
out = make([]interface{}, c)
for i := 0; i < c; i++ {
out[i] = slice.Index(i).Interface()
}
return out, true
}
func takeArg(arg interface{}, kind reflect.Kind) (val reflect.Value, ok bool) {
val = reflect.ValueOf(arg)
if val.Kind() == kind {
ok = true
}
return
}
// ConvertAny2Interface converts interface src to interface slice
func ConvertAny2Interface(src interface{}) ([]interface{}, error) {
data := reflect.ValueOf(src)
if data.Type().Kind() == reflect.Ptr {
data = data.Elem()
}
if data.Type().Kind() != reflect.Slice {
return nil, errors.New("Src not slice")
}
ret := make([]interface{}, data.Len())
for i := 0; i < data.Len(); i++ {
ret[i] = data.Index(i).Interface()
}
return ret, nil
}