Python,压平丑陋的嵌套 for 循环

Pos*_*169 1 python dictionary list cartesian-product python-itertools

我想将多个数据文件通过两个模块来处理它们,使用每个模块的多个参数上的多个设置的每种组合。最明显的方法是使用嵌套的 for 循环,但是当您达到 7 个以上的嵌套 for 循环时,就不行了。我想让这个比那个更优雅。

我已经读过几个非常相似的问题,但是虽然这个问题表明我可能想使用 itertools,但它只迭代数字序列,而我想迭代作为字典中的值包含的字符串列表;另一个揭示了我想要的叫做笛卡尔积,但不是如何从字典值中得到它;虽然这个组合了笛卡尔积中的列表字典,但我希望输出是如上一个链接问题中的列表列表,而不是字典列表。

在:

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']}
Run Code Online (Sandbox Code Playgroud)

出去:

[['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']]
Run Code Online (Sandbox Code Playgroud)

我很确定我想使用itertools,并且我想要制作的是列表的笛卡尔积。我认为目前最困难的事情是从字典中提取这些列表并将其元素的组合放入列表中。

_________编辑:____________

在检查我随后接受的答案的过程中,我发现将所有参数都放在列表中(对于我的目的而言)很重要,即使只考虑一个值;不带方括号的字符串将一次迭代一个字符。

丑陋的嵌套 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)
Run Code Online (Sandbox Code Playgroud)

che*_*ner 5

字典足够小,最简单的方法是将七个参数硬编码为itertools.product:一个“独立”列表、来自 的四个列表CC和来自 的两个列表Noise

from itertools import product
result = list(product(
                  video,
                  CC['size'],
                  CC['font'],
                  CC['color'],
                  CC['language'],
                  Noise['CRT'],
                  Noise['sound']
         ))
Run Code Online (Sandbox Code Playgroud)

您可以使用 稍微简化它operator.itemgetter,这消除了对两个字典的重复提及。

from operator import itemgetter
result = list(product(
                  video,
                  *itemgetter('size', 'font', 'color', 'language')(CC),
                  *itemgetter('CRT', 'sound')(Noise)
         ))
Run Code Online (Sandbox Code Playgroud)

如果您确定字典值的生成顺序,则可以进一步缩短它:

result = list(product(video, *CC.values(), *Noise.values()))
Run Code Online (Sandbox Code Playgroud)

  • 最后一个选择是热爱Python的原因 (2认同)
  • 在 Python 3.6 之前,迭代顺序是任意的。在 Python 3.6 中,顺序由键添加到“dict”的顺序决定,但仅作为 CPython 中的实现细节。该实现细节是 Python 3.7 中的语言要求。 (2认同)