Python,压扁一个丑陋的嵌套 for 循环
Python, flatten an ugly nested for loop
我想把几个数据文件通过两个模块来处理它们,使用每个模块的几个参数的几个设置的每个组合。执行此操作的明显方法是使用嵌套 for 循环,但是当您达到 7+ 嵌套 for 循环时,没有。我想让这个比那个更优雅。
我已经阅读了几个非常相似的问题,但是虽然 this one reveals that I probably want to use itertools, it only iterates through number sequences, while I want to iterate through lists of strings that are contained as values within dictionaries; this other one reveals that what I want is called a Cartesian product, but not how to make that out of dictionary values; and while this one 在笛卡尔乘积中结合了列表字典,但我希望输出是列表列表,就像前面链接的问题一样,而不是词典列表。
在:
video = ["It's Friday.mp4",'Hot Koolaid.mov','The Water Buffalo Song.mp4']
CC = {'size':['6','10','14'],'font':['Courier New'],'color':['black','white'],'language':['English']}
Noise = {'CRT':['speckles','rising stripes','no signal'],'sound':['white','crackle']}
输出:
[['It's Friday.mp4','6','Courier New','black','English','speckles','white'],
['Hot Koolaid.mov','6','Courier New','black','English','speckles','white']
...
['The Water Buffalo Song.mp4','14','Courier New','white','English','no signal','crackle']]
我很确定我想使用 itertools
,而且我想做的是列表的笛卡尔积。我觉得目前最难的是把那些列表从字典里抽出来,然后把它们的元素组合成列表。
_________Edited:____________
在检查我随后接受的答案的过程中,我发现将所有参数都放在列表中很重要(对于我在这里的目的),即使只考虑一个值也是如此;没有方括号的字符串将一次迭代一个字符。
丑陋的嵌套 for 循环如下所示:
for vid in video:
for siz in CC['size']:
for fon in CC['font']:
for col in CC['color']:
for lan in CC['language']:
for crt in Noise['CRT']:
for sou in Noise['sound']:
some_function(vid,siz,fon,col,lan,crt,sou)
字典足够小,最简单的方法是将七个参数硬编码到 itertools.product
:一个 "independent" 列表,四个来自 CC
的列表,两个来自 Noise
.
from itertools import product
result = list(product(
video,
CC['size'],
CC['font'],
CC['color'],
CC['language'],
Noise['CRT'],
Noise['sound']
))
您可以使用 operator.itemgetter
稍微简化一下,这样可以消除对两个词典的重复提及。
from operator import itemgetter
result = list(product(
video,
*itemgetter('size', 'font', 'color', 'language')(CC),
*itemgetter('CRT', 'sound')(Noise)
))
如果您确定字典值的生成顺序,您可以进一步缩短它:
result = list(product(video, *CC.values(), *Noise.values()))
如果您可以对数据做一些适度的调整,使每个键都有一个值(如 {'language': 'English'}
),或者每个视频对应的值列表(如 {'color':['black','black','white']}
),您还可以使用 pandas 制作漂亮的 table 数据。一个例子是这样的:
video = ["It's Friday.mp4",'Hot Koolaid.mov','The Water Buffalo Song.mp4']
CC = {'size':['6','10','14'],'font':'Courier New','color':['black','black','white'],'language':'English'}
Noise = {'CRT':['speckles','rising stripes','no signal'],'sound':['white','white','crackle']}
video_df = pd.DataFrame()
video_df['video'] = video
for key in CC.keys():
video_df[key] = CC[key]
for key in Noise.keys():
video_df[key] = Noise[key]
video_df.values.tolist()
这将生成如下所示的列表列表:
[["It's Friday.mp4",
'6',
'Courier New',
'black',
'English',
'speckles',
'white'],
['Hot Koolaid.mov',
'10',
'Courier New',
'black',
'English',
'rising stripes',
'white'],
['The Water Buffalo Song.mp4',
'14',
'Courier New',
'white',
'English',
'no signal',
'crackle']]
我想把几个数据文件通过两个模块来处理它们,使用每个模块的几个参数的几个设置的每个组合。执行此操作的明显方法是使用嵌套 for 循环,但是当您达到 7+ 嵌套 for 循环时,没有。我想让这个比那个更优雅。
我已经阅读了几个非常相似的问题,但是虽然 this one reveals that I probably want to use itertools, it only iterates through number sequences, while I want to iterate through lists of strings that are contained as values within dictionaries; this other one reveals that what I want is called a Cartesian product, but not how to make that out of dictionary values; and while this one 在笛卡尔乘积中结合了列表字典,但我希望输出是列表列表,就像前面链接的问题一样,而不是词典列表。
在:
video = ["It's Friday.mp4",'Hot Koolaid.mov','The Water Buffalo Song.mp4']
CC = {'size':['6','10','14'],'font':['Courier New'],'color':['black','white'],'language':['English']}
Noise = {'CRT':['speckles','rising stripes','no signal'],'sound':['white','crackle']}
输出:
[['It's Friday.mp4','6','Courier New','black','English','speckles','white'],
['Hot Koolaid.mov','6','Courier New','black','English','speckles','white']
...
['The Water Buffalo Song.mp4','14','Courier New','white','English','no signal','crackle']]
我很确定我想使用 itertools
,而且我想做的是列表的笛卡尔积。我觉得目前最难的是把那些列表从字典里抽出来,然后把它们的元素组合成列表。
_________Edited:____________
在检查我随后接受的答案的过程中,我发现将所有参数都放在列表中很重要(对于我在这里的目的),即使只考虑一个值也是如此;没有方括号的字符串将一次迭代一个字符。
丑陋的嵌套 for 循环如下所示:
for vid in video:
for siz in CC['size']:
for fon in CC['font']:
for col in CC['color']:
for lan in CC['language']:
for crt in Noise['CRT']:
for sou in Noise['sound']:
some_function(vid,siz,fon,col,lan,crt,sou)
字典足够小,最简单的方法是将七个参数硬编码到 itertools.product
:一个 "independent" 列表,四个来自 CC
的列表,两个来自 Noise
.
from itertools import product
result = list(product(
video,
CC['size'],
CC['font'],
CC['color'],
CC['language'],
Noise['CRT'],
Noise['sound']
))
您可以使用 operator.itemgetter
稍微简化一下,这样可以消除对两个词典的重复提及。
from operator import itemgetter
result = list(product(
video,
*itemgetter('size', 'font', 'color', 'language')(CC),
*itemgetter('CRT', 'sound')(Noise)
))
如果您确定字典值的生成顺序,您可以进一步缩短它:
result = list(product(video, *CC.values(), *Noise.values()))
如果您可以对数据做一些适度的调整,使每个键都有一个值(如 {'language': 'English'}
),或者每个视频对应的值列表(如 {'color':['black','black','white']}
),您还可以使用 pandas 制作漂亮的 table 数据。一个例子是这样的:
video = ["It's Friday.mp4",'Hot Koolaid.mov','The Water Buffalo Song.mp4']
CC = {'size':['6','10','14'],'font':'Courier New','color':['black','black','white'],'language':'English'}
Noise = {'CRT':['speckles','rising stripes','no signal'],'sound':['white','white','crackle']}
video_df = pd.DataFrame()
video_df['video'] = video
for key in CC.keys():
video_df[key] = CC[key]
for key in Noise.keys():
video_df[key] = Noise[key]
video_df.values.tolist()
这将生成如下所示的列表列表:
[["It's Friday.mp4",
'6',
'Courier New',
'black',
'English',
'speckles',
'white'],
['Hot Koolaid.mov',
'10',
'Courier New',
'black',
'English',
'rising stripes',
'white'],
['The Water Buffalo Song.mp4',
'14',
'Courier New',
'white',
'English',
'no signal',
'crackle']]