github.com/aarzilli/tools@v0.0.0-20151123112009-0d27094f75e0/sort/sortmap/int-or-string-keyed-generic.go (about) 1 // Package sortmap sorts map[string]int by int; as required in histograms; 2 // it also contains useless map[string]interface{} and map[int]interface{} sorting. 3 package sortmap 4 5 import ( 6 "fmt" 7 "reflect" 8 "sort" 9 ) 10 11 // StringKeysToSortedArray() is a helper to print maps in a sorted key order. 12 // We extract the keys and sort those into an array. 13 // For printing we loop over the !array! instead over the map. 14 // Deplorably, our map values need type interface 15 // 16 // But we do not need this generify stuff anyway. 17 // Just inline it: 18 // keys := make([]int, 0, len(mapAny)) 19 // for k := range mapAny { 20 // keys = append(keys, k) 21 // } 22 // sort.Ints(keys) // or Strings... 23 // for _, k := range keys { 24 // doSomething := mapAny[k] 25 // } 26 func StringKeysToSortedArray(m map[string]interface{}) (keys []string) { 27 keys = make([]string, 0, len(m)) 28 for key, _ := range m { 29 keys = append(keys, key) 30 } 31 sort.Strings(keys) 32 return 33 } 34 35 // IntKeysToSortedArray is like StringKeysToSortedArray, but for int 36 func IntKeysToSortedArray(m map[int]interface{}) (keys []int) { 37 keys = make([]int, 0, len(m)) 38 for key, _ := range m { 39 keys = append(keys, key) 40 } 41 sort.Ints(keys) 42 return 43 } 44 45 // MapGenerifyType32168 converts some special map into a map[string]interface{}. 46 // The function argument is too specific. 47 // We need to rewrite it for every other slice type. 48 func MapGenerifyType32168(m map[int][]int) (ret map[string]interface{}) { 49 ret = make(map[string]interface{}) 50 for k, v := range m { 51 ret[fmt.Sprintf("%02v", k)] = v 52 } 53 return ret 54 } 55 56 // IntegerFieldToSortedArray tries a generic approach to extract 57 // an int out of any slice type. 58 // I dont like it because of the O(n) reflecion. 59 // Also: The argument slice once again needs to be created first. 60 func IntegerFieldToSortedArray(m []interface{}, fieldName string) (vKeys []int) { 61 if len(m) > 1000 { 62 panic("this uses reflection - not for large structs") 63 } 64 vKeys = make([]int, len(m)) 65 for i, iface := range m { 66 vKeys[i] = GetIntField(iface, fieldName) 67 } 68 sort.Ints(vKeys) 69 return 70 } 71 72 // fStudy is based on this 73 // http://stackoverflow.com/questions/6395076/in-golang-using-reflect-how-do-you-set-the-value-of-a-struct-field 74 func GetIntField(myStruct interface{}, fieldName string) (ret int) { 75 76 ps := reflect.ValueOf(&myStruct) // pointer to a struct => addressable 77 s := ps.Elem() 78 if s.Kind() == reflect.Struct { 79 // exported field 80 f := s.FieldByName(fieldName) 81 if f.IsValid() { 82 // A Value can be changed only if it is 83 // addressable and was not obtained by 84 // the use of unexported struct fields. 85 if f.CanSet() { // instead of CanAdr 86 if f.Kind() == reflect.Int { 87 // the "set" case is incommented: 88 // x := int64(7) 89 // if !f.OverflowInt(x) { 90 // f.SetInt(x) 91 // } 92 ret = int(f.Int()) 93 } else { 94 panic("not an int") 95 } 96 } else { 97 panic("field can not set") 98 } 99 } else { 100 panic("field invalid") 101 } 102 } else { 103 panic("not a struct") 104 } 105 return 106 }