如何使用映射或过滤器而不是列表推导过滤特定值的嵌套字典(pythonic 方式)?

Posted

技术标签:

【中文标题】如何使用映射或过滤器而不是列表推导过滤特定值的嵌套字典(pythonic 方式)?【英文标题】:How to filter a nested dictionary (pythonic way) for a specific value using map or filter instead of list comprehensions? 【发布时间】:2017-01-03 20:37:34 【问题描述】:

我有一个嵌套字典。

>>> foo = 'm': 'a': 10, 'n': 'a': 20
>>> 

我想根据“a”的值过滤特定值。

我可以为此目的使用列表推导。

>>> [foo[n] for n in foo if foo[n]['a'] == 10]
['a': 10]
>>> 

单独使用 list 给了我来自 foo 的元素(而不是元素的值) - 正如预期的那样:

>>> list(filter(lambda x: foo[x] if foo[x]['a']==10 else None,foo))
['m']
>>> 

使用 map 会返回不需要的“无”值:

>>> list(map(lambda x: foo[x] if foo[x]['a']==10 else None,foo))
['a': 10, None]
>>> 

结合这两者,我可以获取所需的值。但我猜 foo 被迭代了两次——过滤器和地图各一次。列表理解解决方案只需要我迭代一次。

>>> list(map(lambda t: foo[t], filter(lambda x: foo[x] if foo[x]['a']==10 else None,foo)))
['a': 10]
>>> 

这是另一种仅使用过滤器的方法。这给了我想要的值,但我不确定迭代字典的值是否是一种好的/pythonic 方法:

>>> list(filter(lambda x: x if x['a'] == 10 else None, foo.values()))
['a': 10]
>>> 

我想知道:

    对于这种情况,pythonic/推荐的方法是什么? 如果最后一个对字典值使用过滤器的示例可以接受?

问候

沙拉

【问题讨论】:

为什么要使用 map/filter 而不是列表推导?列表推导通常更 Pythonic。 您想要的结果是什么?是['a': 10]吗?是['m']吗?还是别的什么? pythonic 的方式是使用列表推导,而不是映射或过滤。因此,就目前而言,您的问题无法得到回答。 @John:想要的结果 ['a': 10]。谢谢大家! 【参考方案1】:

列表推导可以很好地做到这一点。

>>> foo = 'm': 'a': 10, 'n': 'a': 20
>>> [v for v in foo.values() if 10 in v.values()]
['a': 10]

如果要与字典中的已知键匹配,则不需要 for 循环或列表推导。

In [15]: if 10 in foo['m'].values():
    ...:     result = [foo['m']]
    ...:     

In [16]: result
Out[16]: ['a': 10]

【讨论】:

【参考方案2】:

如果要返回包含a 的完整嵌套字典,列表推导式可能是最简洁的方法。您的初始列表理解将起作用:

[foo[n] for n in foo if foo[n]['a'] == 10]

您还可以通过以下方式避免在n 上查找:

[d for d in foo.values() if d['a'] == 10]

列表推导通常被认为比 mapfilter 相关的方法更适合像这样的简单问题,但如果您使用预定义的函数,mapfilter 肯定有它们的位置。

这给了我想要的值,但我不确定迭代字典的值是否是一种好的/pythonic 方法。

如果您想返回满足特定条件的字典的所有值,我不确定您将如何绕过遍历字典的值。 p>

对于基于过滤器的方法,我会这样做:

list(filter(lambda x: x['a'] == 10, foo.values()))

您的原始代码中不需要if-else

【讨论】:

基于过滤器方法的示例将返回列表,而不是字典。 嗨,如果我们想过滤这个字典并维护键,那么输出将是 'm': 'a': 10..list(filter(lambda x: x['a'] == 10, foo.values())) 返回 ['a': 10] 我将其更改为 list(filter(lambda x: foo[x]['a'] = = 10, foo)) 然后返回 ['m']。 实际上,我在 foo.items() 中使用 for 循环 ....new_foo = dict() for(k,v) 找到了答案: if v['a'] == 10 : new_foo[k] = v ... 有没有更优雅的方法来使用 lambda 表达式?

以上是关于如何使用映射或过滤器而不是列表推导过滤特定值的嵌套字典(pythonic 方式)?的主要内容,如果未能解决你的问题,请参考以下文章

取消嵌套命中和取消嵌套会话范围的自定义维度 BigQuery 代码过滤器

嵌套的一对多关系 sqlalchemy 过滤

使用过滤器或折叠球拍遍历嵌套列表

如何在使用 MapReduce API 映射到云存储之前过滤数据存储数据?

如何使用 reactjs 和 graphql 在 gatsby 中映射嵌套数组

Yii2 gridview过滤来自多个值的列表(不是下拉列表过滤器)