基于键值对在Python中过滤嵌套字典

3

如何基于键值在Python中过滤嵌套字典:

d = {'data': {'country': 'US', 'city': 'New York', 'state': None},
     'tags': ['US', 'New York'],
     'type': 'country_info',
     'growth_rate': None
     }

我希望过滤这个字典,以消除NoneType值,因此得到的字典应该是:

d = {'data': {'country': 'US', 'city': 'New York'},
     'tags': ['US', 'New York'],
     'type': 'country_info',
     }

此外,该字典可以有多个嵌套级别。我希望从字典中删除所有的NoneType值。
2个回答

10
您可以使用字典推导式轻松地进行递归定义。
def remove_keys_with_none_values(item):
    if not hasattr(item, 'items'):
        return item
    else:
        return {key: remove_keys_with_none_values(value) for key, value in item.items() if value is not None}

递归在Python中并不是很优化,但考虑到可能的嵌套数量相对较小,我不会担心。

在跳跃之前进行查找虽然不太Pythonic,但我认为这比捕获异常更好-因为大多数情况下该值不是一个dict(我们可能有更多的叶子而不是分支)。

还要注意,在Python 2.x中,您可能需要将items()替换为iteritems()


1
我喜欢你的回答,这可能有点挑剔,但是“if value is not None”读起来更好。 - Brian Hicks
@Lattyware:为什么“字典推导式”链接到一个关于列表推导式的YouTube视频?因为它们很相似吗? - benregn
@benregn 这个视频继续讲解了其他类型的推导式和生成器表达式。 - Gareth Latty
有没有一个能在Python 2.6中运行的版本(长话短说)?最后一行在2.6中有语法错误,我猜想这是在2.7中理解方式改变导致的。 - machomeautoguy
@machomeautoguy 在2.7之前不存在字典推导式 - 您可以用调用dict()和生成器表达式来代替它,例如:dict((key, value) for x in y) - Gareth Latty
显示剩余3条评论

0

我非常感谢@Lattyware的答案。它帮助我过滤嵌套对象并删除空值,无论类型是dictlist还是str

这是我想出来的:

remove-keys-with-empty-values.py

# remove-keys-with-empty-values.py
from pprint import pprint

def remove_keys_with_empty_values(item):
  if hasattr(item, 'items'):
    return {key: remove_keys_with_empty_values(value) for key, value in item.items() if value==0 or value}
  elif isinstance(item, list):
    return [remove_keys_with_empty_values(value) for value in item if value==0 or value]
  else:
    return item

d = {
     'string': 'value',
     'integer': 10,
     'float': 0.5,
     'zero': 0,
     'empty_list': [],
     'empty_dict': {},
     'empty_string': '',
     'none': None,
    }

d['nested_dict'] = d.copy()
l = d.values()
d['nested_list'] = l

pprint({
  "DICT FILTERED": remove_keys_with_empty_values(d),
  "DICT ORIGINAL": d,
  "LIST FILTERED": remove_keys_with_empty_values(l),
  "LIST ORIGINAL": l,
})

执行

python remove-keys-with-empty-values.py
    {'DICT FILTERED': {'float': 0.5,
                       'integer': 10,
                       'nested_dict': {'float': 0.5,
                                       'integer': 10,
                                       'string': 'value',
                                       'zero': 0},
                       'nested_list': [0,
                                       'value',
                                       10,
                                       0.5,
                                       {'float': 0.5,
                                        'integer': 10,
                                        'string': 'value',
                                        'zero': 0}],
                       'string': 'value',
                       'zero': 0},
     'DICT ORIGINAL': {'empty_dict': {},
                       'empty_list': [],
                       'empty_string': '',
                       'float': 0.5,
                       'integer': 10,
                       'nested_dict': {'empty_dict': {},
                                       'empty_list': [],
                                       'empty_string': '',
                                       'float': 0.5,
                                       'integer': 10,
                                       'none': None,
                                       'string': 'value',
                                       'zero': 0},
                       'nested_list': [{},
                                       0,
                                       'value',
                                       None,
                                       [],
                                       10,
                                       0.5,
                                       '',
                                       {'empty_dict': {},
                                        'empty_list': [],
                                        'empty_string': '',
                                        'float': 0.5,
                                        'integer': 10,
                                        'none': None,
                                        'string': 'value',
                                        'zero': 0}],
                       'none': None,
                       'string': 'value',
                       'zero': 0},
     'LIST FILTERED': [0,
                       'value',
                       10,
                       0.5,
                       {'float': 0.5,
                        'integer': 10,
                        'string': 'value',
                        'zero': 0}],
     'LIST ORIGINAL': [{},
                       0,
                       'value',
                       None,
                       [],
                       10,
                       0.5,
                       '',
                       {'empty_dict': {},
                        'empty_list': [],
                        'empty_string': '',
                        'float': 0.5,
                        'integer': 10,
                        'none': None,
                        'string': 'value',
                        'zero': 0}]}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接