|
| 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 | +} |
0 commit comments