Skip to content

Instantly share code, notes, and snippets.

@thesyncim
Last active August 31, 2018 11:07
Show Gist options
  • Save thesyncim/06137668e7c3fe7f8b3091a7441eda03 to your computer and use it in GitHub Desktop.
Save thesyncim/06137668e7c3fe7f8b3091a7441eda03 to your computer and use it in GitHub Desktop.
flatten slice
package flatten
import (
"reflect"
)
//flatten method creates a new slice with all sub-slice elements concatted into it recursively
func Flatten(slice interface{}) []interface{} {
//validate input
//must be a slice
if reflect.TypeOf(slice).Kind() != reflect.Slice {
// this should be avoided and the function should return an error on invalid input
// keep it as it is just to match the exercise function signature
panic("must be a slice")
}
return doFlatten(slice)
}
//doFlatten do the actual work
//this could be simplified if we restrict to int or int64
func doFlatten(slice interface{}) []interface{} {
var result []interface{}
switch v := slice.(type) {
case []interface{}:
for i := range v {
result = append(result, doFlatten(v[i])...)
}
case int, uint, uint64, int64, uint32, int32, uint16, int16, uint8, int8:
result = append(result, v)
case []int:
for i := range v {
result = append(result, v[i])
}
case []uint:
for i := range v {
result = append(result, v[i])
}
case []uint64:
for i := range v {
result = append(result, v[i])
}
case []int64:
for i := range v {
result = append(result, v[i])
}
case []uint32:
for i := range v {
result = append(result, v[i])
}
case []int32:
for i := range v {
result = append(result, v[i])
}
case []uint16:
for i := range v {
result = append(result, v[i])
}
case []int16:
for i := range v {
result = append(result, v[i])
}
case []uint8:
for i := range v {
result = append(result, v[i])
}
case []int8:
for i := range v {
result = append(result, v[i])
}
}
return result
}
package flatten
import (
"reflect"
"testing"
)
func TestFlatten(t *testing.T) {
type args struct {
slice interface{}
}
tests := []struct {
name string
args args
want []interface{}
}{
{
name: "interface",
args: args{
slice: []interface{}{
[]interface{}{
1, 2, []interface{}{
3,
},
},
4,
},
},
want: []interface{}{1, 2, 3, 4},
},
{
name: "mixed unsigned /signed 2",
args: args{
slice: []interface{}{
[]interface{}{
1, 2, []int{
3,
},
},
uint(4),
},
},
want: []interface{}{1, 2, 3, uint(4)},
},
{
name: "mixed unsigned /signed",
args: args{
slice: []interface{}{
[]interface{}{
uint8(1), int16(2), []int{
3,
},
},
uint(4),
},
},
want: []interface{}{uint8(1), int16(2), 3, uint(4)},
},
{
name: "recursive 4 levels",
args: args{
slice: []interface{}{
1,
[]interface{}{
2, []interface{}{
3, []interface{}{
4,
},
},
},
},
},
want: []interface{}{1, 2, 3, 4},
},
{
name: "nothing to do",
args: args{
slice: []interface{}{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.slice); !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