Skip to content

Instantly share code, notes, and snippets.

@sjeandeaux
Last active September 12, 2019 18:43
Show Gist options
  • Save sjeandeaux/873110282580fce47c003a4c4e0e4035 to your computer and use it in GitHub Desktop.
Save sjeandeaux/873110282580fce47c003a4c4e0e4035 to your computer and use it in GitHub Desktop.
Flatten an array. You can play with it here => https://play.golang.org/p/Y2PbROlvyNF
package main
import (
"fmt"
"reflect"
)
//flatten it flattens the array
//It returnes the flatten array.
func flatten(toFlatten []interface{}) []interface{} {
if len(toFlatten) == 0 {
return toFlatten
}
return flattenSub(nil, reflect.ValueOf(toFlatten))
}
//flattenSub flatten an array or slice
//This function returns the flatten array.
//It takes args which is the array of current elements already flatten
// v the current element to manage
func flattenSub(args []interface{}, v reflect.Value) []interface{} {
//if the type v is an interface, it gets the value
if v.Kind() == reflect.Interface {
v = v.Elem()
}
//for an array or a slice, it loops on the elements and calls flattenSub.
switch v.Kind() {
case reflect.Array:
fallthrough
case reflect.Slice:
for i := 0; i < v.Len(); i++ {
args = flattenSub(args, v.Index(i))
}
default:
args = append(args, v.Interface())
}
return args
}
func main() {
toFlatten := []interface{}{
[]interface{}{
[]interface{}{
1,
2,
[]interface{}{3},
},
},
4,
}
fmt.Println(flatten(toFlatten))
}
package main
import (
"reflect"
"testing"
)
func Test_flatten(t *testing.T) {
tests := []struct {
name string
args []interface{}
want []interface{}
}{
{
name: "nil",
args: nil,
want: nil,
},
{
name: "empty",
args: []interface{}{},
want: []interface{}{},
},
{
name: "one element",
args: []interface{}{1},
want: []interface{}{1},
},
{
name: "already flat",
args: []interface{}{1, 2, 3, 4, 5},
want: []interface{}{1, 2, 3, 4, 5},
},
{
name: "flatten",
args: []interface{}{
[]interface{}{
[]interface{}{
1,
2,
[]interface{}{3},
},
},
4,
},
want: []interface{}{1, 2, 3, 4},
},
{
name: "flatten with array",
args: []interface{}{[...]int{1, 2, 3, 4}},
want: []interface{}{1, 2, 3, 4},
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := flatten(tt.args); !reflect.DeepEqual(got, tt.want) {
t.Errorf("flatten() = %v, want %v", got, tt.want)
}
})
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment