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  }