Skip to content

Commit d50c146

Browse files
committed
feat: sorting template functions
1 parent 025381d commit d50c146

File tree

2 files changed

+94
-0
lines changed

2 files changed

+94
-0
lines changed

internal/template/sort.go

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
package template
2+
3+
import (
4+
"reflect"
5+
"sort"
6+
)
7+
8+
// sortStrings returns a sorted array of strings in increasing order
9+
func sortStringsAsc(values []string) []string {
10+
sort.Strings(values)
11+
return values
12+
}
13+
14+
// sortStringsDesc returns a sorted array of strings in decreasing order
15+
func sortStringsDesc(values []string) []string {
16+
sort.Sort(sort.Reverse(sort.StringSlice(values)))
17+
return values
18+
}
19+
20+
type sortable interface {
21+
sort.Interface
22+
set(string, interface{}) error
23+
get() []interface{}
24+
}
25+
26+
type sortableData struct {
27+
data []interface{}
28+
}
29+
30+
func (s sortableData) get() []interface{} {
31+
return s.data
32+
}
33+
34+
func (s sortableData) Len() int { return len(s.data) }
35+
36+
func (s sortableData) Swap(i, j int) { s.data[i], s.data[j] = s.data[j], s.data[i] }
37+
38+
type sortableByKey struct {
39+
sortableData
40+
key string
41+
}
42+
43+
func (s *sortableByKey) set(funcName string, entries interface{}) (err error) {
44+
entriesVal, err := getArrayValues(funcName, entries)
45+
if err != nil {
46+
return
47+
}
48+
s.data = make([]interface{}, entriesVal.Len())
49+
for i := 0; i < entriesVal.Len(); i++ {
50+
s.data[i] = reflect.Indirect(entriesVal.Index(i)).Interface()
51+
}
52+
return
53+
}
54+
55+
// method required to implement sort.Interface
56+
func (s sortableByKey) Less(i, j int) bool {
57+
values := map[int]string{i: "", j: ""}
58+
for k := range values {
59+
if v := reflect.ValueOf(deepGet(s.data[k], s.key)); v.Kind() != reflect.Invalid {
60+
values[k] = v.Interface().(string)
61+
}
62+
}
63+
return values[i] < values[j]
64+
}
65+
66+
// Generalized SortBy function
67+
func generalizedSortBy(funcName string, entries interface{}, s sortable, reverse bool) (sorted []interface{}, err error) {
68+
err = s.set(funcName, entries)
69+
if err != nil {
70+
return nil, err
71+
}
72+
if reverse {
73+
sort.Stable(sort.Reverse(s))
74+
} else {
75+
sort.Stable(s)
76+
}
77+
return s.get(), nil
78+
}
79+
80+
// sortObjectsByKeysAsc returns a sorted array of objects, sorted by object's key field in ascending order
81+
func sortObjectsByKeysAsc(objs interface{}, key string) ([]interface{}, error) {
82+
s := &sortableByKey{key: key}
83+
return generalizedSortBy("sortObjsByKeys", objs, s, false)
84+
}
85+
86+
// sortObjectsByKeysDesc returns a sorted array of objects, sorted by object's key field in descending order
87+
func sortObjectsByKeysDesc(objs interface{}, key string) ([]interface{}, error) {
88+
s := &sortableByKey{key: key}
89+
return generalizedSortBy("sortObjsByKey", objs, s, true)
90+
}

internal/template/template.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ func newTemplate(name string) *template.Template {
6767
"sha1": hashSha1,
6868
"split": strings.Split,
6969
"splitN": strings.SplitN,
70+
"sortStringsAsc": sortStringsAsc,
71+
"sortStringsDesc": sortStringsDesc,
72+
"sortObjectsByKeysAsc": sortObjectsByKeysAsc,
73+
"sortObjectsByKeysDesc": sortObjectsByKeysDesc,
7074
"trimPrefix": trimPrefix,
7175
"trimSuffix": trimSuffix,
7276
"trim": trim,

0 commit comments

Comments
 (0)