【问题标题】:Removing nulls and empty objects of mixed data types from a dictionary with a nested structure从具有嵌套结构的字典中删除混合数据类型的空值和空对象
【发布时间】:2020-06-09 04:18:52
【问题描述】:

在我问的一个类似问题的后面,如何在不同的嵌套级别上清理包含各种数据类型的字典:空值、空列表、空字典等,例如

{
  "key":"value",
  "key1": {},
  "key2": [],
  "key3": True,
  "key4": False,
  "key5": None,
  "key6": [1,2,3],
  "key7": {
    "subkey": "subvalue"
  },
  "key8": {
    "subdict": {
      "subdictkey": "subdictvalue", 
      "subdictkey1": {},
      "subdictkey2": [],
      "subdictkey3": None
    }
  }
}

变成:

{
  "key":"value",
  "key3": True,
  "key4": False,
  "key6": [1,2,3],
  "key7": {
    "subkey": "subvalue"
  },
  "key8": {
    "subdict": {
      "subdictkey": "subdictvalue"
    }
  }
}

该解决方案应该适用于 n 级嵌套(不仅仅是 1 级)。显然我想避免嵌套循环(特别是当 n 可以等于 3 或 4 时),是扁平化结构的唯一解决方案吗?有没有更优雅的处理方式?

编辑: 基于@Ch3steR 的回答并解决我遇到的包含 null 的列表的问题,这是最终的工作函数:

def recur(n_dict,new_d={}):
    global counter
    for key,val in n_dict.items():
        if val or isinstance(val,bool) or (isinstance(val,list) and any(elem is not None for elem in val)):
                if (isinstance(val,list) and any(elem is None for elem in val)):
                   counter=counter+1
                else:
                    new_d={**new_d,**{key:val}}
                    if isinstance(val,dict):
                        new_d[key]=recur(val)

    return new_d

【问题讨论】:

  • 你昨天问了同样的问题。 stackoverflow.com/questions/60381477/… 只需使用递归应用相同的逻辑即可。
  • 我认为添加结构组件是一个足够大的变化,它需要另一个问题,我应该只更新前一个吗?
  • 最好将上一个问题的解决方案合并到回答您当前的问题中。当您有 n 级嵌套字典时,请使用 Recursion.
  • 您在该问题中接受的答案不是 pythonic。并检查list,tuple,dict 是否为空,请使用if data_structure 而不是if len(data_structure)==0,就像您之前接受的答案中提出的那样。

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


【解决方案1】:

在处理任意嵌套的字典时可以使用递归

试试这个。

def recur(n_dict,new_d={}):
    for key,val in n_dict.items():
        if val or isinstance(val,bool):
            new_d={**new_d,**{key:val}}
            if isinstance(val,dict):
                new_d[key]=recur(val)
    return new_d

a={
  "key":"value",
  "key1": {},
  "key2": [],
  "key3": True,
  "key4": False,
  "key5": None,
  "key6": [1,2,3],
  "key7": {
    "subkey": "subvalue"
  },
  "key8": {
    "subdict": {
      "subdictkey": "subdictvalue", 
      "subdictkey1": {},
      "subdictkey2": [],
      "subdictkey3": None
    }
  }
}

print(recur(a))
{'key': 'value',
 'key3': True,
 'key4': False,
 'key6': [1, 2, 3],
 'key7': {'subkey': 'subvalue'},
 'key8': {'subdict': {'subdictkey': 'subdictvalue'}}}

recur(n_dict,new_d={}) 使用可变的默认参数。

注意:

永远不要在原地改变new_d,否则你会遇到this problem.

检查您的默认参数是否更改的一种方法是使用__defaults__

>>>recur(a)
>>>recur.__defaults__
({},) 
>>>recur(a)
>>>recur.__defaults__
({},) 

【讨论】:

  • 非常感谢。您介意解释一下您的函数的第 4 行在做什么吗?另外,如何添加一个额外的条件来删除包含单个 null 的列表,例如[None]。我尝试在函数 or (isinstance(val,list) and any(elem is not None for elem in val) 的第 3 行末尾添加一个额外条件,但没有成功
  • @AJG 你需要稍微调整一下。现在在当前函数中,当valdictionary 时,您会重复出现。现在您需要检查 val 是否是 Iterable 而不是字符串。将其实现到上述函数中。如果未能在下面执行此评论。我会再次添加答案。
  • @AJG 从 cmets 读取代码真的很难。成功了吗?
  • 我用最终的工作代码更新了这个问题,如果你有任何最终的指针?
猜你喜欢
  • 2020-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-14
  • 1970-01-01
  • 2018-04-28
  • 2021-08-10
  • 1970-01-01
相关资源
最近更新 更多