-
Notifications
You must be signed in to change notification settings - Fork 9
/
maps.go
162 lines (148 loc) · 3.76 KB
/
maps.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
package gofp
import (
"reflect"
"strconv"
"strings"
)
// Keys returns all the keys of any map
func Keys(mapData map[string]interface{}) []string {
keys := []string{}
for key := range mapData {
keys = append(keys, key)
}
return keys
}
// Values returns all the keys of any map
func Values(mapData map[string]interface{}) []interface{} {
values := []interface{}{}
for _, value := range mapData {
values = append(values, value)
}
return values
}
// Omit returns a new map containing keys that doesn't exists in the provided omittable Keys
func Omit(mapData map[string]interface{}, omittableKeys []string) map[string]interface{} {
newMap := map[string]interface{}{}
for key, value := range mapData {
if !Contains(StringToInterfaceSlice(omittableKeys), key) {
newMap[key] = value
}
}
return newMap
}
// MapValues returns a map transforming the values applying provided function
func MapValues(mapData map[string]interface{}, fn func(interface{}) interface{}) map[string]interface{} {
newMap := map[string]interface{}{}
for key, value := range mapData {
newMap[key] = fn(value)
}
return newMap
}
// MapKeys returns a map transforming the keys applying provided function
func MapKeys(mapData map[string]interface{}, fn func(interface{}) interface{}) map[string]interface{} {
newMap := map[string]interface{}{}
for key, value := range mapData {
newKey := fn(key).(string)
newMap[newKey] = value
}
return newMap
}
// Pick returns a new map with matched keys
func Pick(mapData map[string]interface{}, keys []string) map[string]interface{} {
newMap := map[string]interface{}{}
for _, key := range keys {
value, ok := mapData[key]
if ok {
newMap[key] = value
}
}
return newMap
}
// Has returns all the keys of any map
func Has(mapData map[string]interface{}, key string) (exists bool) {
_, exists = mapData[key]
return
}
func isMap(data interface{}) (isMap bool) {
if data == nil {
return false
}
_, isMap = data.(map[string]interface{})
return
}
// Extend returns a map extending all the property with given map
func Extend(initialMap map[string]interface{}, extendingMap map[string]interface{}) map[string]interface{} {
newMap := map[string]interface{}{}
for key, value := range initialMap {
newMap[key] = value
}
for key, value := range extendingMap {
if isMap(value) && Has(initialMap, key) && isMap(initialMap[key]) {
newMap[key] = Extend(initialMap[key].(map[string]interface{}), value.(map[string]interface{}))
} else {
newMap[key] = value
}
}
return newMap
}
//Get returns the value by path, if path is invalid returns nil
func Get(args ...interface{}) interface{} {
if len(args) < 2 {
panic("Invalid number of argument. Atleast 2 arguments are required")
}
var (
path string
mapData interface{}
fallback interface{}
)
if len(args) >= 1 {
mapData = args[0]
}
if len(args) >= 2 {
path = args[1].(string)
}
if len(args) >= 3 {
fallback = args[2]
}
if mapData == nil {
return fallback
}
defer func() interface{} {
if r := recover(); r != nil {
return fallback
}
return fallback
}()
data := mapData
paths := strings.Split(path, ".")
for _, key := range paths {
value := reflect.ValueOf(data)
dataType := value.Type().Kind()
if dataType == reflect.Map {
data = data.(map[string]interface{})[key]
continue
}
if dataType == reflect.Slice {
indx, err := strconv.Atoi(key)
if err != nil {
return fallback
}
data = value.Index(indx).Interface().(interface{})
continue
}
if dataType == reflect.Struct {
data = value.FieldByName(key).Interface().(interface{})
continue
}
if dataType == reflect.String {
indx, err := strconv.Atoi(key)
if err != nil {
return fallback
}
data = string(data.(string)[indx])
continue
}
return fallback
}
return data
}