forked from scakemyer/quasar
/
slices.go
121 lines (104 loc) · 2.42 KB
/
slices.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
package util
import "reflect"
// Distinct ...
func Distinct(arr interface{}) (reflect.Value, bool) {
// create a slice from our input interface
slice, ok := takeArg(arr, reflect.Slice)
if !ok {
return reflect.Value{}, ok
}
// put the values of our slice into a map
// the key's of the map will be the slice's unique values
c := slice.Len()
m := make(map[interface{}]bool)
for i := 0; i < c; i++ {
m[slice.Index(i).Interface()] = true
}
mapLen := len(m)
// create the output slice and populate it with the map's keys
out := reflect.MakeSlice(reflect.TypeOf(arr), mapLen, mapLen)
i := 0
for k := range m {
v := reflect.ValueOf(k)
o := out.Index(i)
o.Set(v)
i++
}
return out, ok
}
// Difference ...
func Difference(arrs ...interface{}) (reflect.Value, bool) {
// create a temporary map to hold the contents of the arrays
tempMap := make(map[interface{}]int)
var kind reflect.Kind
var kindHasBeenSet bool
for _, arg := range arrs {
tempArr, ok := Distinct(arg)
if !ok {
return reflect.Value{}, ok
}
// check to be sure the type hasn't changed
if kindHasBeenSet && tempArr.Len() > 0 && tempArr.Index(0).Kind() != kind {
return reflect.Value{}, false
}
if tempArr.Len() > 0 {
kindHasBeenSet = true
kind = tempArr.Index(0).Kind()
}
c := tempArr.Len()
for idx := 0; idx < c; idx++ {
// how many times have we encountered this elem?
if _, ok := tempMap[tempArr.Index(idx).Interface()]; ok {
tempMap[tempArr.Index(idx).Interface()]++
} else {
tempMap[tempArr.Index(idx).Interface()] = 1
}
}
}
// write the final val of the diffMap to an array and return
numElems := 0
for _, v := range tempMap {
if v == 1 {
numElems++
}
}
if len(arrs) == 0 {
return reflect.Value{}, false
}
out := reflect.MakeSlice(reflect.TypeOf(arrs[0]), numElems, numElems)
i := 0
for key, val := range tempMap {
if val == 1 {
v := reflect.ValueOf(key)
o := out.Index(i)
o.Set(v)
i++
}
}
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
}
// StringSliceContains ...
func StringSliceContains(ary []string, q string) bool {
for _, i := range ary {
if i == q {
return true
}
}
return false
}
// IntSliceContains ...
func IntSliceContains(ary []int, q int) bool {
for _, i := range ary {
if i == q {
return true
}
}
return false
}