Last active
January 27, 2017 15:15
-
-
Save thisiscetin/9ef44736479b1399e99981be4ac3d857 to your computer and use it in GitHub Desktop.
int slice at infinite dimension
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package nested | |
import ( | |
"errors" | |
"fmt" | |
"strconv" | |
"testing" | |
"github.com/stretchr/testify/assert" | |
) | |
// NestedBlock, primary data structure for adding dimension to our slices | |
type NestedBlock struct { | |
depth int | |
content int | |
} | |
// NestedSlice holds nested blocks, which can have infinitely many dimensions | |
// through declared depth | |
type NestedSlice []*NestedBlock | |
// ParseNestedSlice parses nested slice to predefined type NestedSlice | |
// which is responsible of holding our custom data structure NestedBlocks | |
func ParseNestedSlice(sliceStr string) (NestedSlice, error) { | |
var ns NestedSlice | |
ns = make([]*NestedBlock, 0, 1) | |
var ( | |
depth int | |
numberStart int | |
) | |
for k, r := range sliceStr { | |
switch r { | |
case '[': | |
depth++ | |
numberStart = k + 1 | |
case ']': | |
depth-- | |
case ',': | |
numberStart = k + 1 | |
continue | |
case ' ': | |
return nil, errors.New("do not use blank spaces on nested slice declaration") | |
default: | |
if k+1 == len(sliceStr) { | |
break | |
} | |
if sliceStr[k+1] == ']' || sliceStr[k+1] == ',' { | |
n, err := strconv.Atoi(sliceStr[numberStart : k+1]) | |
if err != nil { | |
return nil, err | |
} | |
ns = append(ns, &NestedBlock{ | |
depth: depth, | |
content: n, | |
}) | |
} | |
} | |
} | |
// check if input string is in expected format | |
if depth != 0 { | |
return nil, fmt.Errorf("nested slice formatting error %s", sliceStr) | |
} | |
return ns, nil | |
} | |
// Flatten returns nested int slices in one dimension | |
func (ns NestedSlice) Flatten() []int { | |
r := make([]int, 0, len(ns)) | |
for _, nb := range ns { | |
r = append(r, nb.content) | |
} | |
return r | |
} | |
// Test cases below | |
func TestParseNestedSliceSuccess(t *testing.T) { | |
ns, err := ParseNestedSlice("[[1,2,[3]],4]") | |
assert.NoError(t, err) | |
assert.NotNil(t, ns) | |
assert.Equal(t, 4, len(ns)) | |
assert.Equal(t, 1, ns[0].content) | |
assert.Equal(t, 2, ns[1].content) | |
assert.Equal(t, 3, ns[2].content) | |
assert.Equal(t, 4, ns[3].content) | |
assert.Equal(t, 2, ns[0].depth) | |
assert.Equal(t, 2, ns[1].depth) | |
assert.Equal(t, 3, ns[2].depth) | |
assert.Equal(t, 1, ns[3].depth) | |
ns, err = ParseNestedSlice("[[1,2,[3],[4,6]],[4,8],10]") | |
assert.NoError(t, err) | |
assert.NotNil(t, ns) | |
ns, err = ParseNestedSlice("[1,2,3]") | |
assert.NoError(t, err) | |
assert.NotNil(t, ns) | |
for _, nb := range ns { | |
assert.Equal(t, 1, nb.depth) | |
} | |
} | |
func TestParseNestedSliceFailure(t *testing.T) { | |
ns, err := ParseNestedSlice("[[1,2,[3]],4") | |
assert.Error(t, err) | |
assert.Nil(t, ns) | |
ns, err = ParseNestedSlice("[[1,2,[3]], 4]") | |
assert.Error(t, err) | |
assert.Nil(t, ns) | |
ns, err = ParseNestedSlice("[[1,2,[3, 4]") | |
assert.Error(t, err) | |
assert.Nil(t, ns) | |
} | |
func TestFlatten(t *testing.T) { | |
ns, _ := ParseNestedSlice("[[1,2,[3]],4]") | |
s := ns.Flatten() | |
assert.NotEqual(t, 0, len(s)) | |
assert.Equal(t, 1, s[0]) | |
assert.Equal(t, 2, s[1]) | |
assert.Equal(t, 3, s[2]) | |
assert.Equal(t, 4, s[3]) | |
ns, _ = ParseNestedSlice("[[1,2,[3],[4,6]],[4,8],10]") | |
s = ns.Flatten() | |
assert.Equal(t, 1, s[0]) | |
assert.Equal(t, 2, s[1]) | |
assert.Equal(t, 3, s[2]) | |
assert.Equal(t, 4, s[3]) | |
assert.Equal(t, 6, s[4]) | |
assert.Equal(t, 4, s[5]) | |
assert.Equal(t, 8, s[6]) | |
assert.Equal(t, 10, s[7]) | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment