mirror of
https://github.com/gohugoio/hugo.git
synced 2025-01-30 10:11:47 +00:00
Fix sort tpl func to return explicit type value
sort template function returns `[]interface{}` type slice value regardless of its original element type. This fixes it to keep the original element type. For example, if it sorts `map[string]int` type value, it returns `[]int` slice value instead of `[]interface{}` slice value.
This commit is contained in:
parent
c7aa881d90
commit
56534beaf6
2 changed files with 29 additions and 30 deletions
|
@ -875,7 +875,7 @@ func Delimit(seq, delimiter interface{}, last ...interface{}) (template.HTML, er
|
|||
return template.HTML(str), nil
|
||||
}
|
||||
|
||||
func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
|
||||
func Sort(seq interface{}, args ...interface{}) (interface{}, error) {
|
||||
seqv := reflect.ValueOf(seq)
|
||||
seqv, isNil := indirect(seqv)
|
||||
if isNil {
|
||||
|
@ -883,7 +883,7 @@ func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
|
|||
}
|
||||
|
||||
// Create a list of pairs that will be used to do the sort
|
||||
p := pairList{SortAsc: true}
|
||||
p := pairList{SortAsc: true, SliceType: reflect.SliceOf(seqv.Type().Elem())}
|
||||
p.Pairs = make([]pair, seqv.Len())
|
||||
|
||||
for i, l := range args {
|
||||
|
@ -900,7 +900,6 @@ func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
|
|||
}
|
||||
}
|
||||
|
||||
var sorted []interface{}
|
||||
switch seqv.Kind() {
|
||||
case reflect.Array, reflect.Slice:
|
||||
for i := 0; i < seqv.Len(); i++ {
|
||||
|
@ -921,8 +920,7 @@ func Sort(seq interface{}, args ...interface{}) ([]interface{}, error) {
|
|||
default:
|
||||
return nil, errors.New("can't sort " + reflect.ValueOf(seq).Type().String())
|
||||
}
|
||||
sorted = p.sort()
|
||||
return sorted, nil
|
||||
return p.sort(), nil
|
||||
}
|
||||
|
||||
// Credit for pair sorting method goes to Andrew Gerrand
|
||||
|
@ -938,6 +936,7 @@ type pairList struct {
|
|||
Pairs []pair
|
||||
SortByField string
|
||||
SortAsc bool
|
||||
SliceType reflect.Type
|
||||
}
|
||||
|
||||
func (p pairList) Swap(i, j int) { p.Pairs[i], p.Pairs[j] = p.Pairs[j], p.Pairs[i] }
|
||||
|
@ -965,18 +964,18 @@ func (p pairList) Less(i, j int) bool {
|
|||
}
|
||||
|
||||
// sorts a pairList and returns a slice of sorted values
|
||||
func (p pairList) sort() []interface{} {
|
||||
func (p pairList) sort() interface{} {
|
||||
if p.SortAsc {
|
||||
sort.Sort(p)
|
||||
} else {
|
||||
sort.Sort(sort.Reverse(p))
|
||||
}
|
||||
sorted := make([]interface{}, len(p.Pairs))
|
||||
sorted := reflect.MakeSlice(p.SliceType, len(p.Pairs), len(p.Pairs))
|
||||
for i, v := range p.Pairs {
|
||||
sorted[i] = v.Value.Interface()
|
||||
sorted.Index(i).Set(v.Value)
|
||||
}
|
||||
|
||||
return sorted
|
||||
return sorted.Interface()
|
||||
}
|
||||
|
||||
func IsSet(a interface{}, key interface{}) bool {
|
||||
|
|
|
@ -1085,48 +1085,48 @@ func TestSort(t *testing.T) {
|
|||
sequence interface{}
|
||||
sortByField interface{}
|
||||
sortAsc string
|
||||
expect []interface{}
|
||||
expect interface{}
|
||||
}{
|
||||
{[]string{"class1", "class2", "class3"}, nil, "asc", []interface{}{"class1", "class2", "class3"}},
|
||||
{[]string{"class3", "class1", "class2"}, nil, "asc", []interface{}{"class1", "class2", "class3"}},
|
||||
{[]int{1, 2, 3, 4, 5}, nil, "asc", []interface{}{1, 2, 3, 4, 5}},
|
||||
{[]int{5, 4, 3, 1, 2}, nil, "asc", []interface{}{1, 2, 3, 4, 5}},
|
||||
{[]string{"class1", "class2", "class3"}, nil, "asc", []string{"class1", "class2", "class3"}},
|
||||
{[]string{"class3", "class1", "class2"}, nil, "asc", []string{"class1", "class2", "class3"}},
|
||||
{[]int{1, 2, 3, 4, 5}, nil, "asc", []int{1, 2, 3, 4, 5}},
|
||||
{[]int{5, 4, 3, 1, 2}, nil, "asc", []int{1, 2, 3, 4, 5}},
|
||||
// test map sorting by keys
|
||||
{map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, nil, "asc", []interface{}{10, 20, 30, 40, 50}},
|
||||
{map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, nil, "asc", []interface{}{30, 20, 10, 40, 50}},
|
||||
{map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, nil, "asc", []interface{}{"10", "20", "30", "40", "50"}},
|
||||
{map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
|
||||
{map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, nil, "asc", []interface{}{"50", "40", "10", "30", "20"}},
|
||||
{map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, nil, "asc", []interface{}{"10", "20", "30", "40", "50"}},
|
||||
{map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
|
||||
{map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, nil, "asc", []interface{}{"30", "20", "10", "40", "50"}},
|
||||
{map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, nil, "asc", []int{10, 20, 30, 40, 50}},
|
||||
{map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, nil, "asc", []int{30, 20, 10, 40, 50}},
|
||||
{map[string]string{"1": "10", "2": "20", "3": "30", "4": "40", "5": "50"}, nil, "asc", []string{"10", "20", "30", "40", "50"}},
|
||||
{map[string]string{"3": "10", "2": "20", "1": "30", "4": "40", "5": "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}},
|
||||
{map[string]string{"one": "10", "two": "20", "three": "30", "four": "40", "five": "50"}, nil, "asc", []string{"50", "40", "10", "30", "20"}},
|
||||
{map[int]string{1: "10", 2: "20", 3: "30", 4: "40", 5: "50"}, nil, "asc", []string{"10", "20", "30", "40", "50"}},
|
||||
{map[int]string{3: "10", 2: "20", 1: "30", 4: "40", 5: "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}},
|
||||
{map[float64]string{3.3: "10", 2.3: "20", 1.3: "30", 4.3: "40", 5.3: "50"}, nil, "asc", []string{"30", "20", "10", "40", "50"}},
|
||||
// test map sorting by value
|
||||
{map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "value", "asc", []interface{}{10, 20, 30, 40, 50}},
|
||||
{map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "value", "asc", []interface{}{10, 20, 30, 40, 50}},
|
||||
{map[string]int{"1": 10, "2": 20, "3": 30, "4": 40, "5": 50}, "value", "asc", []int{10, 20, 30, 40, 50}},
|
||||
{map[string]int{"3": 10, "2": 20, "1": 30, "4": 40, "5": 50}, "value", "asc", []int{10, 20, 30, 40, 50}},
|
||||
// test map sorting by field value
|
||||
{
|
||||
map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
|
||||
"MyInt",
|
||||
"asc",
|
||||
[]interface{}{ts{10, 10.5, "ten"}, ts{20, 20.5, "twenty"}, ts{30, 30.5, "thirty"}, ts{40, 40.5, "forty"}, ts{50, 50.5, "fifty"}},
|
||||
[]ts{{10, 10.5, "ten"}, {20, 20.5, "twenty"}, {30, 30.5, "thirty"}, {40, 40.5, "forty"}, {50, 50.5, "fifty"}},
|
||||
},
|
||||
{
|
||||
map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
|
||||
"MyFloat",
|
||||
"asc",
|
||||
[]interface{}{ts{10, 10.5, "ten"}, ts{20, 20.5, "twenty"}, ts{30, 30.5, "thirty"}, ts{40, 40.5, "forty"}, ts{50, 50.5, "fifty"}},
|
||||
[]ts{{10, 10.5, "ten"}, {20, 20.5, "twenty"}, {30, 30.5, "thirty"}, {40, 40.5, "forty"}, {50, 50.5, "fifty"}},
|
||||
},
|
||||
{
|
||||
map[string]ts{"1": {10, 10.5, "ten"}, "2": {20, 20.5, "twenty"}, "3": {30, 30.5, "thirty"}, "4": {40, 40.5, "forty"}, "5": {50, 50.5, "fifty"}},
|
||||
"MyString",
|
||||
"asc",
|
||||
[]interface{}{ts{50, 50.5, "fifty"}, ts{40, 40.5, "forty"}, ts{10, 10.5, "ten"}, ts{30, 30.5, "thirty"}, ts{20, 20.5, "twenty"}},
|
||||
[]ts{{50, 50.5, "fifty"}, {40, 40.5, "forty"}, {10, 10.5, "ten"}, {30, 30.5, "thirty"}, {20, 20.5, "twenty"}},
|
||||
},
|
||||
// Test sort desc
|
||||
{[]string{"class1", "class2", "class3"}, "value", "desc", []interface{}{"class3", "class2", "class1"}},
|
||||
{[]string{"class3", "class1", "class2"}, "value", "desc", []interface{}{"class3", "class2", "class1"}},
|
||||
{[]string{"class1", "class2", "class3"}, "value", "desc", []string{"class3", "class2", "class1"}},
|
||||
{[]string{"class3", "class1", "class2"}, "value", "desc", []string{"class3", "class2", "class1"}},
|
||||
} {
|
||||
var result []interface{}
|
||||
var result interface{}
|
||||
var err error
|
||||
if this.sortByField == nil {
|
||||
result, err = Sort(this.sequence)
|
||||
|
|
Loading…
Reference in a new issue