github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/f/mapper.go (about)

     1  package f
     2  
     3  import (
     4  	"reflect"
     5  	"sort"
     6  	"strings"
     7  )
     8  
     9  // MapKeys get all keys of the given map.
    10  func MapKeys(mp interface{}, sorted ...bool) (keys []string) {
    11  	rftVal := reflect.ValueOf(mp)
    12  	if rftVal.Type().Kind() == reflect.Ptr {
    13  		rftVal = rftVal.Elem()
    14  	}
    15  
    16  	if rftVal.Kind() != reflect.Map {
    17  		return
    18  	}
    19  
    20  	for _, key := range rftVal.MapKeys() {
    21  		keys = append(keys, key.String())
    22  	}
    23  
    24  	if len(sorted) > 0 && sorted[0] {
    25  		sort.Strings(keys)
    26  	}
    27  	return
    28  }
    29  
    30  // MapKeysContains map keys contains key.
    31  func MapKeysContains(mp map[string]interface{}, key string) bool {
    32  	for k := range mp {
    33  		if k == key {
    34  			return true
    35  		}
    36  	}
    37  	return false
    38  }
    39  
    40  // MapKeySorted Enable map keys to be retrieved in same order when iterating.
    41  func MapKeySorted(mp map[string]interface{}) (keys []string) {
    42  	for key := range mp {
    43  		keys = append(keys, key)
    44  	}
    45  	sort.Strings(keys)
    46  	return keys
    47  }
    48  
    49  // MapValues get all values from the given map.
    50  func MapValues(mp interface{}) (values []interface{}) {
    51  	rftTyp := reflect.TypeOf(mp)
    52  	if rftTyp.Kind() == reflect.Ptr {
    53  		rftTyp = rftTyp.Elem()
    54  	}
    55  
    56  	if rftTyp.Kind() != reflect.Map {
    57  		return
    58  	}
    59  
    60  	rftVal := reflect.ValueOf(mp)
    61  	for _, key := range rftVal.MapKeys() {
    62  		values = append(values, rftVal.MapIndex(key).Interface())
    63  	}
    64  	return
    65  }
    66  
    67  // MapValuesContains map values contains value.
    68  func MapValuesContains(mp map[string]interface{}, val interface{}) bool {
    69  	for _, v := range mp {
    70  		if reflect.DeepEqual(v, val) {
    71  			return true
    72  		}
    73  	}
    74  	return false
    75  }
    76  
    77  // MapValue get value from a map[string]interface{}. eg "top" "top.sub"
    78  func MapValue(key string, mp map[string]interface{}) (val interface{}, ok bool) {
    79  	if val, ok := mp[key]; ok {
    80  		return val, true
    81  	}
    82  
    83  	// has sub key? eg. "top.sub"
    84  	if !strings.ContainsRune(key, '.') {
    85  		return nil, false
    86  	}
    87  
    88  	keys := strings.Split(key, ".")
    89  	topK := keys[0]
    90  
    91  	// find top item data based on top key
    92  	var item interface{}
    93  	if item, ok = mp[topK]; !ok {
    94  		return
    95  	}
    96  
    97  	for _, k := range keys[1:] {
    98  		switch tData := item.(type) {
    99  		case map[string]string: // is simple map
   100  			item, ok = tData[k]
   101  			if !ok {
   102  				return
   103  			}
   104  		case map[string]interface{}: // is map(decode from toml/json)
   105  			if item, ok = tData[k]; !ok {
   106  				return
   107  			}
   108  		case map[interface{}]interface{}: // is map(decode from yaml)
   109  			if item, ok = tData[k]; !ok {
   110  				return
   111  			}
   112  		default: // error
   113  			ok = false
   114  			return
   115  		}
   116  	}
   117  
   118  	return item, true
   119  }