【问题标题】:delete one level in a python dict keeping the values删除保留值的python dict中的一个级别
【发布时间】:2016-04-20 06:37:54
【问题描述】:

我有以下 python 字典:

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

有什么好的方法可以实现吗?

【问题讨论】:

  • d['load_balancers'] = d['load_balancers']['App']?

标签: python json python-2.7 python-3.x dictionary


【解决方案1】:
derp['load_balancers'] = derp['load_balancers']['App']

【讨论】:

  • 我做了:docs['load_balancers'] = docs['load_balancers'].pop(v.keys()[0], None) 有效,其中 v 是值。
  • 是的,但有一个缺点。如果你只对 v 字典的一个键感兴趣,但它有多个项目,你会得到随机结果,因为 dicts 没有排序!您的方法基本上是“从 v dict 的 'load_balancers' 的第一个随机项中将第一个值放入 docs dict”
【解决方案2】:

虽然这个问题并不需要一个通用的解决方案,但我认为为了未来的搜索者的利益(并且以防 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}

【讨论】:

    【解决方案3】:
    thedict['load_balancers'] = thedict['load_balancers'].pop('App')
    

    【讨论】:

      【解决方案4】:
      dt[dt.keys()[0]] = dt[dt.keys()[0]].values()[0]
      

      【讨论】:

      • 不要忘记字典中项目顺序的随机性。如果 dt 有超过 1 个键,则您的方法的结果会更改每次调用。
      【解决方案5】:

      我在尝试解决类似问题时发现了这个问题。上面有人给出了递归方法,但它使用 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}}}}}
      

      【讨论】:

        猜你喜欢
        • 2023-01-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2023-01-19
        • 2021-11-03
        • 1970-01-01
        • 2018-04-27
        相关资源
        最近更新 更多