mirror of
https://github.com/gohugoio/hugo.git
synced 2024-11-29 10:12:04 -05:00
tpl: Add uniq function
This commit is contained in:
parent
46b4607828
commit
e28d9aa42c
4 changed files with 89 additions and 0 deletions
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Reference in a new issue