Skip to content

Commit

Permalink
Support splitting strings on separators
Browse files Browse the repository at this point in the history
  • Loading branch information
ntnn committed Jan 17, 2024
1 parent 73010b3 commit 5edb3c9
Show file tree
Hide file tree
Showing 3 changed files with 78 additions and 4 deletions.
15 changes: 14 additions & 1 deletion value.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,14 +153,27 @@ func (v Value) To(other any, opts ...ToOption) error {

// List returns the underlying data as a slice of Values.
//
// The passed separators are passed to .ListString if the underlying
// value is a string.
//
// Warning: This method is very simplistic and at the moment only
// returns a proper slice of values if the underlying data is a slice.
func (v Value) List() ([]Value, error) {
func (v Value) List(seps ...string) ([]Value, error) {
if v.Data == nil {
return []Value{}, ErrValueIsNil
}

switch reflect.TypeOf(v.Data).Kind() {
case reflect.String:
s, err := v.ListString(seps...)
if err != nil {
return nil, err
}
vs := make([]Value, len(s))
for i := range s {
vs[i] = NewValue(s[i])
}
return vs, nil
case reflect.Slice:
l := reflect.ValueOf(v.Data)
ret := make([]Value, l.Len())
Expand Down
30 changes: 27 additions & 3 deletions valueString.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,21 @@ func (v Value) TrimString() string {
return strings.TrimSpace(v.MustString())
}

// DefaultStringSeparators is used when no separators are passed,
var DefaultStringSeparators = []string{
",",
"\n",
}

// ListString returns the underlying data as a slice of strings.
//
// If the underlying data is a slice each member is transformed into
// a string using the Value.String method.
//
// If the underlying data is a string the string is split using the
// passed separator.
func (v Value) ListString(sep string) ([]string, error) {
// passed separator. If not separators are passed
// DefaultStringSeparators is used.
func (v Value) ListString(seps ...string) ([]string, error) {
val := reflect.ValueOf(v.Data)
switch val.Kind() {
case reflect.Slice:
Expand All @@ -60,7 +67,24 @@ func (v Value) ListString(sep string) ([]string, error) {
if err != nil {
return nil, fmt.Errorf("dataparse: error turning %q into string to split: %w", v.Data, err)
}
return strings.Split(s, sep), nil

if len(seps) == 0 {
seps = DefaultStringSeparators
}

for _, sep := range seps {
split := strings.Split(s, sep)
if len(split) == 1 {
// walk through separators until more than one element
// is present
continue
}
return split, nil
}

// default to returning the singular element if no separator
// split the element.
return []string{s}, nil
}
}

Expand Down
37 changes: 37 additions & 0 deletions value_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,4 +170,41 @@ func TestValue_List(t *testing.T) {
},
v,
)

v, err = NewValue("1,2,3").List()
assert.Nil(t, err)
assert.Equal(t,
[]Value{
Value{Data: "1"},
Value{Data: "2"},
Value{Data: "3"},
},
v,
)
assert.Equal(t, 1, v[0].MustInt())
assert.Equal(t, 2, v[1].MustInt())
assert.Equal(t, 3, v[2].MustInt())

v, err = NewValue("one,two,three").List()
assert.Nil(t, err)
assert.Equal(t,
[]Value{
Value{Data: "one"},
Value{Data: "two"},
Value{Data: "three"},
},
v,
)

v, err = NewValue("one\ntwo\nthree").List()
assert.Nil(t, err)
assert.Equal(t,
[]Value{
Value{Data: "one"},
Value{Data: "two"},
Value{Data: "three"},
},
v,
)

}

0 comments on commit 5edb3c9

Please sign in to comment.