2017-06-27 16:28:39 +02:00
|
|
|
package generics
|
|
|
|
|
|
|
|
import (
|
|
|
|
"reflect"
|
|
|
|
"sort"
|
|
|
|
)
|
|
|
|
|
|
|
|
type genericSortable []interface{}
|
|
|
|
|
|
|
|
// Sort any []interface{} value.
|
|
|
|
func Sort(data []interface{}) {
|
|
|
|
sort.Sort(genericSortable(data))
|
|
|
|
}
|
|
|
|
|
|
|
|
// Len is part of sort.Interface.
|
|
|
|
func (s genericSortable) Len() int {
|
|
|
|
return len(s)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap is part of sort.Interface.
|
|
|
|
func (s genericSortable) Swap(i, j int) {
|
|
|
|
s[i], s[j] = s[j], s[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Less is part of sort.Interface.
|
|
|
|
func (s genericSortable) Less(i, j int) bool {
|
2017-06-28 15:36:39 +02:00
|
|
|
return Less(s[i], s[j])
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// SortByProperty sorts maps on their key indices.
|
2017-06-29 14:22:12 +02:00
|
|
|
func SortByProperty(data []interface{}, key string, nilFirst bool) {
|
|
|
|
sort.Sort(sortableByProperty{data, key, nilFirst})
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
type sortableByProperty struct {
|
2017-06-29 14:22:12 +02:00
|
|
|
data []interface{}
|
|
|
|
key string
|
|
|
|
nilFirst bool
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
// Len is part of sort.Interface.
|
|
|
|
func (s sortableByProperty) Len() int {
|
|
|
|
return len(s.data)
|
|
|
|
}
|
|
|
|
|
|
|
|
// Swap is part of sort.Interface.
|
|
|
|
func (s sortableByProperty) Swap(i, j int) {
|
|
|
|
data := s.data
|
|
|
|
data[i], data[j] = data[j], data[i]
|
|
|
|
}
|
|
|
|
|
|
|
|
// Less is part of sort.Interface.
|
|
|
|
func (s sortableByProperty) Less(i, j int) bool {
|
|
|
|
// index returns the value at the s.key, if in is a map that contains this key
|
2017-06-28 03:30:47 +02:00
|
|
|
index := func(i int) interface{} {
|
|
|
|
value := s.data[i]
|
|
|
|
rt := reflect.ValueOf(value)
|
2017-06-27 16:28:39 +02:00
|
|
|
if rt.Kind() == reflect.Map && rt.Type().Key().Kind() == reflect.String {
|
2017-06-28 03:30:47 +02:00
|
|
|
elem := rt.MapIndex(reflect.ValueOf(s.key))
|
|
|
|
if elem.IsValid() {
|
|
|
|
return elem.Interface()
|
|
|
|
}
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|
|
|
|
return nil
|
|
|
|
}
|
2017-06-28 03:30:47 +02:00
|
|
|
a, b := index(i), index(j)
|
2017-06-28 15:36:39 +02:00
|
|
|
switch {
|
|
|
|
case a == nil && b == nil:
|
|
|
|
return false
|
|
|
|
case a == nil:
|
2017-06-29 14:22:12 +02:00
|
|
|
return s.nilFirst
|
2017-06-28 15:36:39 +02:00
|
|
|
case b == nil:
|
2017-06-29 14:22:12 +02:00
|
|
|
return !s.nilFirst
|
2017-06-28 15:36:39 +02:00
|
|
|
}
|
2017-06-28 03:30:47 +02:00
|
|
|
return Less(a, b)
|
2017-06-27 16:28:39 +02:00
|
|
|
}
|