Reputation: 3581
I have the following python dictionary:
'load_balancers': {'App': {'DJMatcher': {'security_group': 'sg-618d1c05', 'service_name': 'djmatcher/svc', 'certificateId': 'net', 'health_check_path': '/djmatcherstatus/ma.html', 'DNS': {'fde': {'record_name': 'platform-enrichment-djmatcher', 'ttl': 60}}}}}
Now it basically represents the following YAML:
LoadBalancers:
App:
DJMatcher:
certificateId: 'net'
health_check_path: /djmatcherstatus/ma.html
security_group: *svc_sg1
service_name: *sn
DNS:
fde:
record_name: platform-enrichment-djmatcher
ttl: 60
I want to remove the second level of key - "App" and keep the rest as it is, which means the resulting python dictionary should become this where I delete the key App but the value now becomes the value for its parent key "load_balancers" :
'load_balancers': {'DJMatcher': {'security_group': 'sg-618d1c05', 'service_name': 'djmatcher/svc', 'certificateId': 'net', 'health_check_path': '/djmatcherstatus/ma.html', 'DNS': {'fde': {'record_name': 'platform-enrichment-djmatcher', 'ttl': 60}}}}
Any good way to achieve this ?
Upvotes: 4
Views: 8149
Reputation: 5460
I found this question when trying to resolve a similar issue. Someone above gave a recursive method, but it uses Python 2 syntax, and only allows removing keys based on a "level" number, which didn't serve my purposes. Here's an example using a bit more modern syntax and allows for specifying keys to be removed:
def remove_levels(in_dict, keys_to_remove):
try:
result = {}
for key, value in in_dict.items():
if key in keys_to_remove:
result = {**result, **remove_levels(value, keys_to_remove)}
else:
result[key] = remove_levels(value, keys_to_remove)
return result
except AttributeError:
return in_dict
You'd use it like:
loadbalancers = {
'LoadBalancers': {
'DJMatcher': {
'certificateId': 'net',
'health_check_path': '/djmatcherstatus/ma.html',
'security_group': '*svc_sg1',
'service_name': '*sn',
'DNS': {
'fde': {
'record_name': 'platform-enrichment-djmatcher',
'ttl': 60
}
}
}
}
}
remove_levels(loadbalancers, {"App"})
Output:
{'LoadBalancers': {'DJMatcher': {'certificateId': 'net',
'health_check_path': '/djmatcherstatus/ma.html',
'security_group': '*svc_sg1',
'service_name': '*sn',
'DNS': {'fde': {'record_name': 'platform-enrichment-djmatcher',
'ttl': 60}}}}}
Upvotes: 0
Reputation: 4430
Although the problem does not ask for a general solution, I thought it might be worth working up one for the benefit of future searchers (and in case OP runs into a more complicated situation in the future).
def removeLevel(d, level):
if type(d) != type({}):
return d
if level == 0:
removed = {}
for k, v in d.iteritems():
if type(v) != type({}):
continue
for kk, vv in v.iteritems():
removed[kk] = vv
return removed
removed = {}
for k, v in d.iteritems():
removed[k] = removeLevel(v, level-1)
return removed
This runs recursively until it hits the correct level to remove, then copies all the children keys up.
For example:
>>> d = {'load_balancers': {'App': {'DJMatcher': {'security_group': 'sg-618d1c05', 'service_name': 'djmatcher/svc', 'certificateId': 'net', 'health_check_path': '/djmatcherstatus/ma.html', 'DNS': {'fde': {'record_name': 'platform-enrichment-djmatcher', 'ttl': 60}}}}}}
>>> removeLevel(d, 1)
{'load_balancers': {'DJMatcher': {'security_group': 'sg-618d1c05', 'service_name': 'djmatcher/svc', 'certificateId': 'net', 'DNS': {'fde': {'record_name': 'platform-enrichment-djmatcher', 'ttl': 60}}, 'health_check_path': '/djmatcherstatus/ma.html'}}}
>>> d2 = {'a': {'b':1, 'e':{'f':4}}, 'c':{'d':2}}
>>> removeLevel(d2, 1)
{'a': {'f': 4}, 'c': {}}
>>> removeLevel(d2, 0)
{'b': 1, 'e': {'f': 4}, 'd': 2}
Upvotes: 6