删除每次迭代的dict中的Leaf节点

时间:2016-10-31 15:06:47

标签: python

我有一个样本JSON,如:

{'key1': {'key2': 2, 'key3': 1, 'key4' : 1}}

我想删除每个叶节点一次并使用python打印JSON。

为此,我有用于打印所有叶节点的代码。但是,有人可以帮我写一下动态删除叶子节点的代码 - 一次一个

def print_all_leaf_nodes(data):
    if isinstance(data, dict):
        for item in data.values():
            print_all_leaf_nodes(item)
    elif isinstance(data, list) or isinstance(data, tuple):
        for item in data:
            print_all_leaf_nodes(item)
    else:
        print data

输入:

{'key1': {'key2': 2, 'key3': 1, 'key4' : 1}}

输出:

{'key1': {'key3': 1, 'key4' : 1}}
{'key1': {'key2': 2, 'key4' : 1}}
{'key1': {'key2': 2, 'key3': 1}}

,即对于每次迭代,如果其叶节点,则删除键值对。

注意:即使我能从父级获取密钥路径,但不知道如何删除确切的元素。

例如,如果json是

{ "key1" : { "key2" : { "key3": "value1", "key4" : "value2" }}}

我有递归函数,它返回一个字符串

key_to_be_removed = "key1.key2.key4"

但我不知道如何使用此字符串删除key4。

请帮忙。

2 个答案:

答案 0 :(得分:0)

听起来你有三个不同的问题:

  1. 检测树中的叶节点。
  2. 根据某些条件从字典中删除键值对。
  3. 以递归方式向下执行此操作。
  4. 您有叶节点检测工作。对于后两者,我建议你阅读Comparable

    删除某些值

    要删除删除了某些值的字典副本,您可以在字典理解中使用public boolean CompareTo(Name obj) { if(priority < obj.priority) { return -1; } if (priority > obj.priority) { return 1; } return 0; }

    if

    其中def foo(d): return { key: value for key, value in d.items() if some_condition(key, value) }

    递归

    这是dictionary comprehensions。在递归地将方法应用于字典及其值的情况下,您可以在字典理解中简单地包含递归引用:

    some_condition

答案 1 :(得分:0)

如果我理解你有类似下面的字典:

 g = {
  2: 3,
  4:
      {
          3: 4,
          34: {
              36: 5,
              8: 5,
              7: 9,
              9: 7
          },
          8: 9,
          9: {
              3: 4
          }
      },
  89: 3
  }

此dict表示一般树结构,其中每个节点都可以指向项目或子树。

如果需要迭代树并在每次迭代时返回没有叶子的树,则可以使用生成器。你可以利用python不会深度复制dicts的事实,所以如果你将一个dict传递给一个函数而不是在函数内部弹出一个元素,你还会在函数外面弹出一个元素:

此代码未经测试请测试

# dict, void list -> dict, list
# find the deepest subtree in a nested dict and return the subtree and the path
# to find it. If there isn't subtree return the same dict and a void list
  def _mostNestedSubTree(tree, nodes):
      for key in tree:
          if isinstance(tree[key], dict):
              nodes.append(key)
              return _mostNestedSubTree(tree[key], nodes)
      return tree, nodes


  # dict, list -> dict
  # pop a nested element from a dict (tree) following the path in a list (nodes)
  def _recursivePop(tree, nodes):
      if len(nodes) > 1:
          print(tree, nodes[0])
          tree = tree[nodes[0]]
          return _recursivePop(tree, nodes[1:])
      else:
          print(tree, nodes[0])
          tree.pop(nodes[0])
          return tree


  def removeOneLeaf(tree):
      mostNestedDict, nodes = _mostNestedSubTree(tree, [])
      while mostNestedDict != tree:
          if len(mostNestedDict) > 1:
              mostNestedDict.pop(list(mostNestedDict)[0])
          else:
              _recursivePop(tree, nodes)
          mostNestedDict, nodes = _mostNestedSubTree(tree, [])
          yield tree

另一种方法是创建一个更好地呈现你的树的对象,例如你可以开始注意你可以用下面的内容来表示g

myTree = {
    tree: [3, 4, 5, 5, 9, 4],
    nodes: [2,4,[3,34,[36,8],8,9,[9,[3,4]]]]
    }