tpl: Add uniq function

This commit is contained in:
Nathan Sharfi 2017-05-29 12:03:38 -07:00 committed by Bjørn Erik Pedersen
parent 46b4607828
commit e28d9aa42c
4 changed files with 89 additions and 0 deletions

View file

@ -373,6 +373,15 @@ e.g.
{{ .Content }}
{{ end }}
### uniq
Takes in a slice or array and returns a slice with subsequent duplicate elements removed.
{{ uniq (slice 1 2 3 2) }}
{{ slice 1 2 3 2 | uniq }}
<!-- both return [1 2 3] -->
## Files
### readDir

View file

@ -587,3 +587,41 @@ func (ns *Namespace) Union(l1, l2 interface{}) (interface{}, error) {
return nil, errors.New("can't iterate over " + reflect.ValueOf(l1).Type().String())
}
}
// Uniq takes in a slice or array and returns a slice with subsequent
// duplicate elements removed.
func (ns *Namespace) Uniq(l interface{}) (interface{}, error) {
if l == nil {
return make([]interface{}, 0), nil
}
lv := reflect.ValueOf(l)
lv, isNil := indirect(lv)
if isNil {
return nil, errors.New("invalid nil argument to Uniq")
}
var ret reflect.Value
switch lv.Kind() {
case reflect.Slice:
ret = reflect.MakeSlice(lv.Type(), 0, 0)
case reflect.Array:
ret = reflect.MakeSlice(reflect.SliceOf(lv.Type().Elem()), 0, 0)
default:
return nil, errors.New("Can't use Uniq on " + reflect.ValueOf(lv).Type().String())
}
for i := 0; i != lv.Len(); i++ {
lvv := lv.Index(i)
lvv, isNil := indirect(lvv)
if isNil {
continue
}
if !ns.In(ret.Interface(), lvv.Interface()) {
ret = reflect.Append(ret, lvv)
}
}
return ret.Interface(), nil
}

View file

@ -603,6 +603,42 @@ func TestUnion(t *testing.T) {
}
}
func TestUniq(t *testing.T) {
t.Parallel()
ns := New(&deps.Deps{})
for i, test := range []struct {
l interface{}
expect interface{}
isErr bool
}{
{[]string{"a", "b", "c"}, []string{"a", "b", "c"}, false},
{[]string{"a", "b", "c", "c"}, []string{"a", "b", "c"}, false},
{[]string{"a", "b", "b", "c"}, []string{"a", "b", "c"}, false},
{[]string{"a", "b", "c", "b"}, []string{"a", "b", "c"}, false},
{[]int{1, 2, 3}, []int{1, 2, 3}, false},
{[]int{1, 2, 3, 3}, []int{1, 2, 3}, false},
{[]int{1, 2, 2, 3}, []int{1, 2, 3}, false},
{[]int{1, 2, 3, 2}, []int{1, 2, 3}, false},
{[4]int{1, 2, 3, 2}, []int{1, 2, 3}, false},
{nil, make([]interface{}, 0), false},
// should-errors
{1, 1, true},
{"foo", "fo", true},
} {
errMsg := fmt.Sprintf("[%d] %v", i, test)
result, err := ns.Uniq(test.l)
if test.isErr {
assert.Error(t, err, errMsg)
continue
}
assert.NoError(t, err, errMsg)
assert.Equal(t, test.expect, result, errMsg)
}
}
func (x *TstX) TstRp() string {
return "r" + x.A
}

View file

@ -137,6 +137,12 @@ func init() {
{`{{ seq 3 }}`, `[1 2 3]`},
},
)
ns.AddMethodMapping(ctx.Uniq,
[]string{"uniq"},
[][2]string{
{`{{ slice 1 2 3 2 | uniq }}`, `[1 2 3]`},
},
)
return ns