【问题标题】:Creating a new dictionary from mapping of flattened nested dictionary从扁平嵌套字典的映射创建新字典
【发布时间】:2015-06-10 15:48:55
【问题描述】:

我想知道是否有一种基于字典的某些键的快速且 Pythonic 的方法来创建字典?

例如,如果我有这个给定的字典

{
  "a": "abc",
  "b": {"b1": "1", "b2": "2", "b3": "3"},
  "c": 1,
  "d": "timmy",
  "e": "John"
}

我希望能够仅基于给定字典的几个键创建一个具有一对一映射的新字典。所以在这个例子中,我想创建一个仅基于键 "b2""c""d" 的字典。我也想给这些键一个不同的名字。期望的输出是:

{
  "out_b2": "2",
  "out_c": 1,
  "out_d": "timmy"
}

我能想到的最简单的过程是创建嵌套的 for 循环来执行此任务。我想知道是否有更有效的方法来实现这一目标。

我知道他的问题可能会根据输入和输出的情况而令人困惑。让我们保持简单,说最深层次是输入的最大一个子字典,输出不会有任何子字典

【问题讨论】:

  • 很不清楚。你能再举一些例子吗?会不会有更多的子目录?
  • @tobias_k 我想我能理解你为什么会感到困惑。我会尽快更新问题
  • 好吧,你无法避免必须递归地展平所有嵌套的 subdicts,除非你有一些启发式方法知道 key b2 位于 subdict d['b'],或者除非所有需要的 key 恰好是在顶层找到。您还需要告诉我们更多缺失的信息吗?我们是否应该根据与顶级键的排序相似性来猜测接下来要递归到什么?这听起来比递归更麻烦。

标签: python dictionary nested flatten


【解决方案1】:

您可以遍历您的字典项目并检查值是否为dict 再次循环其项目并检查键是否在您指定的键中,然后将项目添加到新字典:

>>> old={
...   "a": "abc",
...   "b": {"b1": "1", "b2": "2", "b3": "3"},
...   "c": 1,
...   "d": "timmy",
...   "e": "John"
... }
>>> new={}
>>> for i, j in old.items():
...    if i in key:
...        new['out_'+i]=j
...    elif isinstance(j,dict):
...         for k, v in j.items():
...              if k in key:
...                   new['out_'+k]=v
... 
>>> new
{'out_d': 'timmy', 'out_b2': '2', 'out_c': 1}

【讨论】:

    【解决方案2】:

    我会使用另一个字典来保存从旧名称到所需名称的映射:

    mappings = {
        'b.b2': 'out_b2',
        'c': 'out_c',
        'd': 'out_d',
    }
    

    在这里,我在键中使用了 . 来表示嵌套字典的子键 - 如果您的键中可能包含 .,请使用不同的分隔符(例如,/) .我会使用一个辅助函数将该点子键符号转换为一个值:

    def get_node(d, path):
        if '.' not in path:
            return d[path]
        first, rest = path.split('.', 1)
        return get_node(d[first], rest)
    

    然后得到你想要的钥匙是微不足道的:

    >>> old = {
      "a": "abc",
      "b": {"b1": "1", "b2": "2", "b3": "3"},
      "c": 1,
      "d": "timmy",
      "e": "John"
    }
    >>> {v: get_node(old, k) for k, v in mappings.iteritems()}
    {'out_b2': '2', 'out_c': 1, 'out_d': 'timmy'}
    

    我在最后一部分中使用了字典理解 - 如果您的 Python 版本不支持它,您可以使用以下内容:

    dict((v, get_node(old, k)) for k, v in mappings.iteritems())
    

    【讨论】:

      猜你喜欢
      • 2018-11-09
      • 1970-01-01
      • 2021-07-28
      • 2011-08-27
      • 1970-01-01
      • 2019-02-04
      • 2018-03-27
      相关资源
      最近更新 更多