...
1 package funk
2
3 import (
4 "fmt"
5 "reflect"
6 "strings"
7 )
8
9
10
11 func Filter(arr interface{}, predicate interface{}) interface{} {
12 if !IsIteratee(arr) {
13 panic("First parameter must be an iteratee")
14 }
15
16 if !IsFunction(predicate, 1, 1) {
17 panic("Second argument must be function")
18 }
19
20 funcValue := reflect.ValueOf(predicate)
21
22 funcType := funcValue.Type()
23
24 if funcType.Out(0).Kind() != reflect.Bool {
25 panic("Return argument should be a boolean")
26 }
27
28 arrValue := reflect.ValueOf(arr)
29
30 arrType := arrValue.Type()
31
32
33 resultSliceType := reflect.SliceOf(arrType.Elem())
34
35
36 resultSlice := reflect.MakeSlice(resultSliceType, 0, 0)
37
38 for i := 0; i < arrValue.Len(); i++ {
39 elem := arrValue.Index(i)
40
41 result := funcValue.Call([]reflect.Value{elem})[0].Interface().(bool)
42
43 if result {
44 resultSlice = reflect.Append(resultSlice, elem)
45 }
46 }
47
48 return resultSlice.Interface()
49 }
50
51
52
53 func Find(arr interface{}, predicate interface{}) interface{} {
54 _, val := FindKey(arr, predicate)
55 return val
56 }
57
58
59
60 func FindKey(arr interface{}, predicate interface{}) (matchKey, matchEle interface{}) {
61 if !IsIteratee(arr) {
62 panic("First parameter must be an iteratee")
63 }
64
65 if !IsFunction(predicate, 1, 1) {
66 panic("Second argument must be function")
67 }
68
69 funcValue := reflect.ValueOf(predicate)
70
71 funcType := funcValue.Type()
72
73 if funcType.Out(0).Kind() != reflect.Bool {
74 panic("Return argument should be a boolean")
75 }
76
77 arrValue := reflect.ValueOf(arr)
78 var keyArrs []reflect.Value
79
80 isMap := arrValue.Kind() == reflect.Map
81 if isMap {
82 keyArrs = arrValue.MapKeys()
83 }
84 for i := 0; i < arrValue.Len(); i++ {
85 var (
86 elem reflect.Value
87 key reflect.Value
88 )
89 if isMap {
90 key = keyArrs[i]
91 elem = arrValue.MapIndex(key)
92 } else {
93 key = reflect.ValueOf(i)
94 elem = arrValue.Index(i)
95 }
96
97 result := funcValue.Call([]reflect.Value{elem})[0].Interface().(bool)
98
99 if result {
100 return key.Interface(), elem.Interface()
101 }
102 }
103
104 return nil, nil
105 }
106
107
108
109 func IndexOf(in interface{}, elem interface{}) int {
110 inValue := reflect.ValueOf(in)
111
112 elemValue := reflect.ValueOf(elem)
113
114 inType := inValue.Type()
115
116 if inType.Kind() == reflect.String {
117 return strings.Index(inValue.String(), elemValue.String())
118 }
119
120 if inType.Kind() == reflect.Slice {
121 equalTo := equal(elem)
122 for i := 0; i < inValue.Len(); i++ {
123 if equalTo(reflect.Value{}, inValue.Index(i)) {
124 return i
125 }
126 }
127 }
128
129 return -1
130 }
131
132
133
134 func LastIndexOf(in interface{}, elem interface{}) int {
135 inValue := reflect.ValueOf(in)
136
137 elemValue := reflect.ValueOf(elem)
138
139 inType := inValue.Type()
140
141 if inType.Kind() == reflect.String {
142 return strings.LastIndex(inValue.String(), elemValue.String())
143 }
144
145 if inType.Kind() == reflect.Slice {
146 length := inValue.Len()
147
148 equalTo := equal(elem)
149 for i := length - 1; i >= 0; i-- {
150 if equalTo(reflect.Value{}, inValue.Index(i)) {
151 return i
152 }
153 }
154 }
155
156 return -1
157 }
158
159
160 func Contains(in interface{}, elem interface{}) bool {
161 inValue := reflect.ValueOf(in)
162 elemValue := reflect.ValueOf(elem)
163 inType := inValue.Type()
164
165 switch inType.Kind() {
166 case reflect.String:
167 return strings.Contains(inValue.String(), elemValue.String())
168 case reflect.Map:
169 equalTo := equal(elem, true)
170 for _, key := range inValue.MapKeys() {
171 if equalTo(key, inValue.MapIndex(key)) {
172 return true
173 }
174 }
175 case reflect.Slice, reflect.Array:
176 equalTo := equal(elem)
177 for i := 0; i < inValue.Len(); i++ {
178 if equalTo(reflect.Value{}, inValue.Index(i)) {
179 return true
180 }
181 }
182 default:
183 panic(fmt.Sprintf("Type %s is not supported by Contains, supported types are String, Map, Slice, Array", inType.String()))
184 }
185
186 return false
187 }
188
189
190 func Every(in interface{}, elements ...interface{}) bool {
191 for _, elem := range elements {
192 if !Contains(in, elem) {
193 return false
194 }
195 }
196 return true
197 }
198
199
200 func Some(in interface{}, elements ...interface{}) bool {
201 for _, elem := range elements {
202 if Contains(in, elem) {
203 return true
204 }
205 }
206 return false
207 }
208
View as plain text