@@ -98,7 +98,7 @@ func ToMap(in interface{}, pivot string) interface{} {
9898 return collection .Interface ()
9999}
100100
101- func mapSlice (arrValue reflect.Value , funcValue reflect.Value ) interface {} {
101+ func mapSlice (arrValue reflect.Value , funcValue reflect.Value ) reflect. Value {
102102 funcType := funcValue .Type ()
103103
104104 if funcType .NumIn () != 1 || funcType .NumOut () == 0 || funcType .NumOut () > 2 {
@@ -125,7 +125,7 @@ func mapSlice(arrValue reflect.Value, funcValue reflect.Value) interface{} {
125125 resultSlice = reflect .Append (resultSlice , result )
126126 }
127127
128- return resultSlice . Interface ()
128+ return resultSlice
129129 }
130130
131131 if funcType .NumOut () == 2 {
@@ -141,13 +141,13 @@ func mapSlice(arrValue reflect.Value, funcValue reflect.Value) interface{} {
141141 collection .SetMapIndex (results [0 ], results [1 ])
142142 }
143143
144- return collection . Interface ()
144+ return collection
145145 }
146146
147- return nil
147+ return reflect. Value {}
148148}
149149
150- func mapMap (arrValue reflect.Value , funcValue reflect.Value ) interface {} {
150+ func mapMap (arrValue reflect.Value , funcValue reflect.Value ) reflect. Value {
151151 funcType := funcValue .Type ()
152152
153153 if funcType .NumIn () != 2 || funcType .NumOut () == 0 || funcType .NumOut () > 2 {
@@ -170,7 +170,7 @@ func mapMap(arrValue reflect.Value, funcValue reflect.Value) interface{} {
170170 resultSlice = reflect .Append (resultSlice , result )
171171 }
172172
173- return resultSlice . Interface ()
173+ return resultSlice
174174 }
175175
176176 // two parameters, should be a map
@@ -188,14 +188,24 @@ func mapMap(arrValue reflect.Value, funcValue reflect.Value) interface{} {
188188
189189 }
190190
191- return collection . Interface ()
191+ return collection
192192 }
193193
194- return nil
194+ return reflect. Value {}
195195}
196196
197197// Map manipulates an iteratee and transforms it to another type.
198198func Map (arr interface {}, mapFunc interface {}) interface {} {
199+ result := mapFn (arr , mapFunc , "Map" )
200+
201+ if result .IsValid () {
202+ return result .Interface ()
203+ }
204+
205+ return nil
206+ }
207+
208+ func mapFn (arr interface {}, mapFunc interface {}, funcName string ) reflect.Value {
199209 if ! IsIteratee (arr ) {
200210 panic ("First parameter must be an iteratee" )
201211 }
@@ -214,13 +224,50 @@ func Map(arr interface{}, mapFunc interface{}) interface{} {
214224
215225 if kind == reflect .Slice || kind == reflect .Array {
216226 return mapSlice (arrValue , funcValue )
227+ } else if kind == reflect .Map {
228+ return mapMap (arrValue , funcValue )
217229 }
218230
219- if kind == reflect .Map {
220- return mapMap (arrValue , funcValue )
231+ panic (fmt .Sprintf ("Type %s is not supported by " + funcName , arrType .String ()))
232+ }
233+
234+ // FlatMap manipulates an iteratee and transforms it to a flattened collection of another type.
235+ func FlatMap (arr interface {}, mapFunc interface {}) interface {} {
236+ result := mapFn (arr , mapFunc , "FlatMap" )
237+
238+ if result .IsValid () {
239+ return flatten (result ).Interface ()
240+ }
241+
242+ return nil
243+ }
244+
245+ // Flatten flattens a two-dimensional array.
246+ func Flatten (out interface {}) interface {} {
247+ return flatten (reflect .ValueOf (out )).Interface ()
248+ }
249+
250+ func flatten (value reflect.Value ) reflect.Value {
251+ sliceType := value .Type ()
252+
253+ if (value .Kind () != reflect .Slice && value .Kind () != reflect .Array ) ||
254+ (sliceType .Elem ().Kind () != reflect .Slice && sliceType .Elem ().Kind () != reflect .Array ) {
255+ panic ("Argument must be an array or slice of at least two dimensions" )
256+ }
257+
258+ resultSliceType := sliceType .Elem ().Elem ()
259+
260+ resultSlice := reflect .MakeSlice (reflect .SliceOf (resultSliceType ), 0 , 0 )
261+
262+ length := value .Len ()
263+
264+ for i := 0 ; i < length ; i ++ {
265+ item := value .Index (i )
266+
267+ resultSlice = reflect .AppendSlice (resultSlice , item )
221268 }
222269
223- panic ( fmt . Sprintf ( "Type %s is not supported by Map" , arrType . String ()))
270+ return resultSlice
224271}
225272
226273// FlattenDeep recursively flattens array.
@@ -233,18 +280,18 @@ func flattenDeep(value reflect.Value) reflect.Value {
233280
234281 resultSlice := reflect .MakeSlice (reflect .SliceOf (sliceType ), 0 , 0 )
235282
236- return flatten (value , resultSlice )
283+ return flattenRecursive (value , resultSlice )
237284}
238285
239- func flatten (value reflect.Value , result reflect.Value ) reflect.Value {
286+ func flattenRecursive (value reflect.Value , result reflect.Value ) reflect.Value {
240287 length := value .Len ()
241288
242289 for i := 0 ; i < length ; i ++ {
243290 item := value .Index (i )
244291 kind := item .Kind ()
245292
246293 if kind == reflect .Slice || kind == reflect .Array {
247- result = flatten (item , result )
294+ result = flattenRecursive (item , result )
248295 } else {
249296 result = reflect .Append (result , item )
250297 }
0 commit comments