【问题标题】:Inverting a python dictionary反转python字典
【发布时间】:2020-06-11 02:08:23
【问题描述】:

我有一本看起来像这样的字典:

normalDictionary = {'a' : {'b': {}},
                    'a1': {'b1': {'c1' : {},
                                  'd1' : {}}}}

我想将其反转,使其看起来像:

invertedDictionary = {'d1': {'b1': {'a1': {}}},
                      'c1': {'b1': {'a1': {}}},
                      'b': {'a': {}}}

那个 python 函数会是什么样子?

我似乎无法过去:

def invert_dictionary( node, leafName, indent ):

    keys = list( node.keys() )
    keys.sort()

    constructed = { leafName: {} }

    for key in keys:

        inverted = invert_dictionary( node[ key ], key, indent + 4 )


    return constructed

invertedDictionary = {}

for key in normalDictionary
    inverted = invert_dictionary( normalDictionary[ key ], key, indent = 0 )

【问题讨论】:

  • 您漂亮的打印顺序有点混乱。您可能希望确保相同的顺序。
  • 字典越深入,缩进越多。
  • 是的,但请查看invertedDictionary = { ... } 订单。底行首先打印得很漂亮。
  • 漂亮的打印顺序无关紧要...仅用于演示目的。看看 normalDictionary 和 reverseDictionary。
  • 是的,一分钟左右我就明白了;我只是担心其他可能想回答您问题的人。

标签: python algorithm dictionary recursion


【解决方案1】:

这可能不是最佳算法,但您可以从这个开始。这个想法是

  • 我们将字典转换为从“根”到所有“叶子”的所有“步行路径”
  • 然后我们以相反的顺序从这些路径构建另一个字典

代码如下:

def getpaths(dictionary, pathhead):
    if not dictionary:
        return [pathhead]
    paths = []
    for key in dictionary:
        paths.extend(getpaths(dictionary[key], pathhead+[key]))
    return paths

def invert(dictionary):
    paths = getpaths(dictionary, [])
    inverted = {}
    for path in paths:
        head = inverted
        for node in path[::-1]:
            if node not in head:
                head[node] = {}
            head = head[node]
    return inverted

这就是它的工作原理:

>>> normalDictionary
{'a': {'b': {}}, 'a1': {'b1': {'c1': {}, 'd1': {}}}}
>>> invert(normalDictionary)
{'b': {'a': {}}, 'c1': {'b1': {'a1': {}}}, 'd1': {'b1': {'a1': {}}}}

【讨论】:

  • 这里有很多很好的答案。许多人可能已被标记为答案。我选择这个是因为 (a) 它有效,(b) 它是第一个,并且 (c) 我喜欢它。
【解决方案2】:

递归实现:

def asdict(xs: list) -> dict:
    return {} if len(xs) == 0 else {xs[0]: asdict(xs[1:])}

def inverted_dict_as_tuples(d: dict, stack: list):
    for k, v in d.items():
        if len(v) == 0:
            yield (k, *reversed(stack))
        else:
            yield from inverted_dict_as_tuples(v, [*stack, k])

def inverted_dict(d: dict) -> dict:
    return {x: asdict(xs) for x, *xs in inverted_dict_as_tuples(d, [])}

用法:

>>> import json
>>> d = {"a": {"b": {}}, "a1": {"b1": {"c1": {}, "d1": {}}}}
>>> print(json.dumps(d, indent=2))
{
  "a": {
    "b": {}
  },
  "a1": {
    "b1": {
      "c1": {},
      "d1": {}
    }
  }
}

>>> d_inv = inverted_dict(d)
>>> print(json.dumps(d_inv, indent=2))
{
  "b": {
    "a": {}
  },
  "c1": {
    "b1": {
      "a1": {}
    }
  },
  "d1": {
    "b1": {
      "a1": {}
    }
  }
}

【讨论】:

    【解决方案3】:

    这是一个可行的解决方案:

    def add_path(d, path):
        while path:
            k = path.pop()
            if k not in d:
                d[k] = {}
            d = d[k]
    
    
    def invert_dict(d, target=None, path=None):
        if target is None:
            target = {}
        if path is None:
            path = []
        if not d:
            add_path(target, path)
        else:
            for k, v in d.items():
                invert_dict(v, target, path + [k])
        return target
    
    
    print(invert_dict(normalDictionary))
    

    不过,这假设您的字典仅包含与您的示例类似的字典。不确定实际用例是什么,您可能有更多混合数据类型。

    结果:

    {'b': {'a': {}}, 'c1': {'b1': {'a1': {}}}, 'd1': {'b1': {'a1': {}}}}
    

    【讨论】:

      【解决方案4】:

      我想你想要一个这样的递归函数。

      def reverse_dict(final_result, middle_result, normal_dictionary):
          for key, value in normal_dictionary.items():
              if len(value.keys()) == 0:
                  final_result[key] = value
                  middle_result.append(final_result[key])
              else:
                  reverse_dict(final_result, middle_result, value)
                  for item in middle_result:
                      item[key] = {}
                  middle_result = []
                  for item in middle_result:
                      middle_result.append(item[key])
      

      例子:

      test_normal_dictionary = {
          'a': {
              'b': {}
          },
          'a1': {
              'b1': {
                  'c1': {},
                  'd1': {}
              }
          }
      }
      result_dictionary = {}
      print(f"Origin dict: {test_normal_dictionary}")
      reverse_dict(result_dictionary, [], test_normal_dictionary)
      print(f"Reversed dict: {result_dictionary}")
      

      输出:

      Origin dict: {'a': {'b': {}}, 'a1': {'b1': {'c1': {}, 'd1': {}}}}
      Reversed dict: {'b': {'a': {}}, 'c1': {'b1': {}, 'a1': {}}, 'd1': {'b1': {}, 'a1': {}}}
      

      【讨论】:

        猜你喜欢
        • 2021-08-21
        • 2013-01-11
        • 1970-01-01
        • 1970-01-01
        • 2011-03-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多