Scooby
Scooby

Reputation: 3581

delete one level in a python dict keeping the values

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

Answers (5)

PMende
PMende

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

user812786
user812786

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

AlokThakur
AlokThakur

Reputation: 3741

dt[dt.keys()[0]] = dt[dt.keys()[0]].values()[0]

Upvotes: 0

Chad S.
Chad S.

Reputation: 6633

thedict['load_balancers'] = thedict['load_balancers'].pop('App')

Upvotes: 2

Nicolas Heimann
Nicolas Heimann

Reputation: 2581

derp['load_balancers'] = derp['load_balancers']['App']

Upvotes: 10

Related Questions