删除Python字典中的一级键,同时保留值。

4

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}}}}}

现在它基本上代表以下的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

我希望删除第二层键“App”,并保留其余部分,这意味着生成的Python字典应该变成这样,其中我删除了键“App”,但是值现在变为其父键“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}}}}

有什么好的方法可以实现这个目标吗?

2
d['load_balancers'] = d['load_balancers']['App']? d['load_balancers'] = d['load_balancers']['App']? - JCVanHamme
5个回答

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

1
我执行了以下操作:docs['load_balancers'] = docs['load_balancers'].pop(v.keys()[0], None),这个操作是有效的,其中v是值。 - Scooby
2
是的,但它有一个缺点。如果您只对v字典中的一个键感兴趣,但它有多个条目,则由于字典未排序,您将获得随机结果!您的方法基本上是“从v字典的'load_balancers'的第一个随机项中,将第一个值放入docs字典”。 - Nicolas Heimann

6
虽然问题没有要求提供通用解决方案,但我认为为了未来的搜索者(以及以防万一OP在将来遇到更加复杂的情况),提供一个通用解决方案可能会有所帮助。
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

这个程序会递归地运行直到找到需要移除的正确层级,然后将所有子键复制上移。

例如:

>>> 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}

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

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

1
不要忘记字典中项目的顺序是随机的。如果dt含有一个以上的键,那么你的方法每次被调用时结果都会改变。 - Nicolas Heimann

0
我在解决类似问题时发现了这个问题。有人提供了一种递归方法,但它使用的是Python 2语法,并且只允许根据“级别”数字删除键,这并不符合我的要求。下面是一个示例,使用了更现代的语法,并允许指定要删除的键:
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

你可以这样使用:

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"})

输出:

{'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}}}}}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接