[英]List Comprehension of Lists Nested in Dictionaries
我有一个字典,其中每个值都是一个列表,如下所示:
dictA = {1:['a','b','c'],2:['d','e']}
不幸的是,我无法改变这种结构来解决我的问题
我想将列表的所有条目收集到一个列表中,如下所示:
['a','b','c','d','e']
另外,我想在if-block中只执行一次。 由于我只想做一次,我不想将它存储到一个中间变量,所以自然地,列表理解是要走的路。 但是怎么样? 我的第一个猜测,
[dictA[key] for key in dictA.keys()]
产量,
[['a','b','c'],['d','e']]
哪个不起作用,因为
'a' in [['a','b','c'],['d','e']]
收益False
。 我尝试的其他所有内容都使用了某种非法语法。
我怎么能表现出这样的理解力呢?
循环遍历返回的列表(直接在字典上循环也为您提供键):
[value for key in dictA for value in dictA[key]]
或更直接使用dictA.itervalues()
:
[value for lst in dictA.itervalues() for value in lst]
列表推导让你嵌套循环; 阅读上面的循环,好像它们以相同的顺序嵌套:
for lst in dictA.itervalues():
for value in lst:
# append value to the output list
或者使用itertools.chain.from_iterable()
:
from itertools import chain
list(chain.from_iterable(dictA.itervalues()))
后者采用一系列序列,让你循环遍历它们,好像它们是一个大的列表。 dictA.itervalues()
为您提供了一系列列表,并且chain()
将它们放在一起以便list()
迭代并构建一个大列表。
如果你所做的只是测试所有值中的成员资格,那么你真正想要的是一种简单的方法来遍历所有的值,并测试你的值,直到你找到匹配。 any()
函数和合适的生成器表达式就是这样:
any('a' in lst for lst in dictA.itervalues())
一旦dictA
中'a'
任何值列出'a'
,就会返回True
并且尽早停止循环.itervalues()
。
如果您实际上正在检查成员身份(您的a in...
示例),您可以将其重写为:
if any('a' in val for val in dictA.itervalues()):
# do something
如果实际上不需要,则可以节省必须压缩列表。
在这种特殊情况下,您可以使用嵌套理解:
[value for key in dictA.keys() for value in dictA[key]]
但总的来说,如果你已经想出如何将某些东西变成嵌套列表,你可以使用chain.from_iterable
来展平任何嵌套的iterable:
itertools.chain.from_iterable(dictA[key] for key in dictA.keys())
这将返回一个迭代器,而不是一个列表; 如果您需要一个列表,请明确地执行:
list(itertools.chain.from_iterable(dictA[key] for key in dictA.keys()))
作为旁注, for key in dictA.keys()
中的for key in dictA
相同的for key in dictA
,除了在旧版本的Python中,它会浪费时间和内存来创建一个额外的键列表。 正如文档所说, dict
上的iter
与iterkeys
相同。
所以,在上面的所有版本中,最好只in dictA
使用。
在简单的代码中只是为了理解这可能会有所帮助
ListA=[]
dictA = {1:['a','b','c'],2:['d','e']}
for keys in dictA:
for values in dictA[keys]:
ListA.append(values)
你可以做一些像..
output_list = []
[ output_list.extend(x) for x in {1:['a','b','c'],2:['d','e']}.values()]
output_list将是['a','b','c','d','e']
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.