OB.DAAC Logo
NASA Logo
Ocean Color Science Software

ocssw V2022
DictUtils.py
Go to the documentation of this file.
1 #! /usr/bin/python3
2 
3 import re
4 
5 def __matches(regex, textlist):
6  """Returns subset of input textlist which matches regex."""
7  return [item for item in textlist if re.match(regex, item)]
8 
9 
10 def promote_value(mydict, keyregex):
11  """
12  Assign value of a single-item inner dictionary to its outer key.
13  (cut out the middleman)
14 
15  mydict = {'OUTER': {'INNER': val}}
16  promote_value(mydict, 'IN.*')
17  mydict => {'OUTER': val}
18  """
19  for k, v in list(mydict.items()):
20  if isinstance(v, dict):
21  promote_value(v, keyregex)
22  if len(list(v.keys())) == 1 and re.match(keyregex, list(v.keys())[0]):
23  mydict[k] = v[list(v.keys())[0]]
24 
25 
26 def promote_dict(mydict, keyregex):
27  """
28  A single-item inner dictionary takes the place of its outer key.
29  (level up)
30 
31  mydict = {'OUTER': {'INNER': val}}
32  promote_dict(mydict, 'IN.*')
33  mydict => {'INNER': val}
34  """
35  for k, v in list(mydict.items()):
36  if isinstance(v, dict):
37  promote_dict(v, keyregex)
38  if len(list(v.keys())) == 1 and re.match(keyregex, list(v.keys())[0]):
39  key = list(v.keys())[0]
40  if key not in mydict:
41  mydict[key] = v[key]
42  del mydict[k]
43 
44 
45 def flatten_dict(mydict):
46  """
47  All keys are promoted, as long as a key of the same name does not exist at the upper level.
48 
49  mydict = {'OUTER': {'INNER1': {'INNER2': {'INNER3': val}}}}
50  flatten_dict(mydict)
51  mydict => {'INNER3': val}
52  """
53  for k, v in list(mydict.items()):
54  if isinstance(v, dict):
55  flatten_dict(v)
56  for key in list(v.keys()):
57  if key not in mydict:
58  mydict[key] = v[key]
59  del v[key]
60  if not len(list(v.keys())):
61  del mydict[k]
62 
63 
64 def delete_key(mydict, keyregex):
65  """
66  Remove all keys with name matching keyregex from nested dictionary.
67 
68  mydict = {'OUTER': {'INNER1': {'INNER2': {'INNER3': val}}}}
69  delete_key(mydict, '*.2')
70  mydict => {'OUTER': {'INNER1': {}}}
71  """
72  for v in list(mydict.values()):
73  if isinstance(v, dict):
74  delete_key(v, keyregex)
75  for k in __matches(keyregex, list(mydict.keys())):
76  del mydict[k]
77 
78 
79 def delete_empty(mydict):
80  """
81  Remove empty dictionaries from nested dictionary.
82 
83  mydict = {'OUTER': {'INNER': val}, 'EMPTY': {'EMPTY': {}}}
84  delete_empty(mydict)
85  mydict => {'OUTER': {'INNER': val} }
86  """
87  for k, v in list(mydict.items()):
88  if isinstance(v, dict):
89  delete_empty(v)
90  if not len(list(v.keys())):
91  del mydict[k]
92 
93 
94 def reassign_keys_in_dict(mydict, namekey, valuekey):
95  """
96  Combine two key/value pairs.
97 
98  mydict = {'OUTER': {'namekey': 'key', 'valuekey': val}}
99  reassign_keys_in_dict(mydict, 'namekey', 'valuekey')
100  mydict => {'OUTER': {'key': val}}
101  """
102  for v in list(mydict.values()):
103  if isinstance(v, dict):
104  reassign_keys_in_dict(v, namekey, valuekey)
105  try:
106  v[v[namekey]] = v[valuekey]
107  del v[namekey]
108  del v[valuekey]
109  except (KeyError, TypeError): pass
110 
111 
112 def _allkeys(mydict, myset):
113  myset.update(mydict)
114  for d in mydict.values():
115  if isinstance(d, dict):
116  _allkeys(d, myset)
117 
118 
119 def allkeys(mydict):
120  """Return list of all unique keys in dictionary."""
121  myset = set()
122  _allkeys(mydict, myset)
123  return sorted(myset)
124 
125 #--------------------------------------------------------------------------
126 
127 if __name__ == "__main__":
128  import time
129 
130  def __dotest(cmd, dict1, dict2):
131  print("\n", cmd)
132  print("before: ", dict1)
133  start_time = time.time()
134  exec(cmd)
135  end_time = time.time()
136  print("after: ", dict1)
137  print("target: ", dict2)
138  print(1000 * (end_time - start_time), "ms")
139 
140  val = 99
141 
142  cmd = "promote_value(dict1, 'IN.*')"
143  dict1 = {'OUTER': {'INNER': val}}
144  dict2 = {'OUTER': val}
145  __dotest(cmd, dict1, dict2)
146 
147  cmd = "promote_dict(dict1, 'IN.*')"
148  dict1 = {'OUTER': {'INNER': val}}
149  dict2 = {'INNER': val}
150  __dotest(cmd, dict1, dict2)
151 
152  cmd = "flatten_dict(dict1)"
153  dict1 = {'OUTER': {'INNER1': {'INNER2': {'INNER3': val}}}}
154  dict2 = {'INNER3': val}
155  __dotest(cmd, dict1, dict2)
156 
157  cmd = "delete_key(dict1, '.*2')"
158  dict1 = {'OUTER': {'INNER1': {'INNER2': {'INNER3': val}}}}
159  dict2 = {'OUTER': {'INNER1': {}}}
160  __dotest(cmd, dict1, dict2)
161 
162  cmd = "delete_empty(dict1)"
163  dict1 = {'OUTER': {'INNER': val}, 'EMPTY': {'EMPTY': {}}}
164  dict2 = {'OUTER': {'INNER': val}}
165  __dotest(cmd, dict1, dict2)
166 
167  cmd = "reassign_keys_in_dict(dict1, 'namekey', 'valuekey')"
168  dict1 = {'OUTER': {'namekey': 'key', 'valuekey': val}}
169  dict2 = {'OUTER': {'key': val}}
170  __dotest(cmd, dict1, dict2)
def promote_value(mydict, keyregex)
Definition: DictUtils.py:10
def delete_key(mydict, keyregex)
Definition: DictUtils.py:64
list(APPEND LIBS ${PGSTK_LIBRARIES}) add_executable(atteph_info_modis atteph_info_modis.c) target_link_libraries(atteph_info_modis $
Definition: CMakeLists.txt:7
def flatten_dict(mydict)
Definition: DictUtils.py:45
def delete_empty(mydict)
Definition: DictUtils.py:79
def promote_dict(mydict, keyregex)
Definition: DictUtils.py:26
def allkeys(mydict)
Definition: DictUtils.py:119
def reassign_keys_in_dict(mydict, namekey, valuekey)
Definition: DictUtils.py:94