Due to the lapse in federal government funding, NASA is not updating this website. We sincerely regret this inconvenience.
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 ${NETCDF_LIBRARIES}) find_package(GSL REQUIRED) include_directories($
Definition: CMakeLists.txt:8
def flatten_dict(mydict)
Definition: DictUtils.py:45
def delete_empty(mydict)
Definition: DictUtils.py:79
void print(std::ostream &stream, const char *format)
Definition: PrintDebug.hpp:38
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