使用格式化的字符串的所有排列

时间:2018-04-14 06:14:31

标签: python formatting permutation

我有一个字符串模板,我想从中生成文件名。它现在使用带有命名占位符的百分比格式,并且可以有任意数量的要替换的部分。

template = "image_%(uval)02d_%(vval)02d.%(frame)04d.tif"

我有一个包含占位符键和值列表的对象:

params = {
    "uval": [1,2],
    "vval": [1,2],
    "frame": [10,11]
}

我想用格式生成排列:

[
    "image_01_01.0010.tif",
    "image_01_01.0011.tif",
    "image_01_02.0010.tif",
    "image_01_02.0011.tif",
    "image_02_01.0010.tif",
    "image_02_01.0011.tif",
    "image_02_02.0010.tif",
    "image_02_02.0011.tif"
]

所以我尝试了这个:

def permutations(template, params):
    # loop through params, each time replacing expanded with the 
    # new list of resolved filenames. 
    expanded = [template]
    for param in params:
        newlist = []
        for filename in expanded:
            for number in params[param]:
                newlist.append(filename % {param: number})
        expanded = newlist
    return expanded


print permutations(template, params)

问题是:

newlist.append(filename % {param: number})
KeyError: 'uval'

由于它一次替换一个键,因此每次迭代中只存在一个占位符,因此不存在的占位符会导致错误。理想情况下,在更换一个密钥时,它应该保持模板的其余部分不受影响。

如果当然只有一个占位符,它可以正常工作:

template = "image.%(frame)04d.tif"
params = {"frame": [10, 11]}
print permutations(template, params)
Result: ['image.0010.tif', 'image.0011.tif']

我不介意使用其他系统,但理想情况下我希望模板字符串具有表现力且易于推理。

欢迎提示

1 个答案:

答案 0 :(得分:3)

我使用itertools.product来选择参数,并为每个组合构建一个字典,以便在格式化步骤中使用,该步骤一次性替换所有占位符:

import itertools

def permutations(template, params):
    for vals in itertools.product(*params.values()):
        substituion_dict = dict(zip(params, vals))
        yield template % substituion_dict

这是一个生成器函数,因此它返回一个迭代器而不是结果列表。要打印它,您需要先将迭代器传递给list。但是,如果您的真实代码要执行其他操作(例如在for循环中循环结果,对每个循环执行某些操作),您可能根本不需要创建列表。您可以直接从生成器函数循环迭代器。