【发布时间】:2015-09-11 00:16:16
【问题描述】:
我有生成列表的笛卡尔积的生成器函数。真正的应用程序使用更复杂的对象,但它们可以用字符串来表示:
import itertools
s1 = ['a', 'b']
s2 = ['c', 'd', 'e', 'f']
s3 = ['c', 'd', 'e', 'f']
s4 = ['g']
p = itertools.product(*[s1,s2,s3,s4])
names = [''.join(s) for s in p]
在本例中,结果是 32 个字符组合:
names
['accg', 'acdg', 'aceg', 'acfg', 'adcg', 'addg', 'adeg', 'adfg', 'aecg',
'aedg', 'aeeg', 'aefg', 'afcg', 'afdg', 'afeg', 'affg', 'bccg', 'bcdg',
'bceg', 'bcfg', 'bdcg', 'bddg', 'bdeg', 'bdfg', 'becg', 'bedg', 'beeg',
'befg', 'bfcg', 'bfdg', 'bfeg', 'bffg']
现在,假设我有一些限制,例如某些字符组合是非法的。例如,假设只允许包含正则表达式 '[ab].c' 的字符串。 ('a' 或 'b' 后接任意字母,后接 'c')
应用这些约束后,我们只剩下 8 个字符串的缩减集:
import re
r = re.compile('[ab].c')
filter(r.match, names)
['accg', 'adcg', 'aecg', 'afcg', 'bccg', 'bdcg', 'becg', 'bfcg']
在实际应用程序中,链更长,可能有数千种组合,并且应用数百个约束是相当计算密集型的,因此我担心可扩展性。
现在我正在检查每一个组合并检查其有效性。是否存在可以加快这一过程的算法/数据结构?
编辑: 也许这会澄清一点:在实际应用程序中,我从简单的基本块(如柱子、屋顶段、窗户等)组装建筑物的随机 2D 图片。这些约束限制了可以将哪种类型的块(及其旋转)组合在一起,因此生成的随机图像看起来很逼真,而不是随机的混乱。
给定的约束可以包含多种模式组合。但在所有这些组合中,许多组合都是无效的,因为不同的约束会禁止其中的某些部分。因此,在我的示例中,一个约束将包含上述字符的完整笛卡尔积。第二个约束是'[ab].c';这第二个约束减少了我需要考虑的第一个约束的有效组合的数量。
因为这些约束很难创建;我希望可视化每个约束中的所有块组合的样子,但只有通过所有约束的 valid 组合。因此我的问题。谢谢!
【问题讨论】:
-
不要将迭代器强制转换为 list(),只需在列表理解中使用迭代器(p 当前所在的位置)。
-
好收获!我编辑了示例。
-
s3 = ['c']不也能正常工作吗?也就是说,与其过滤输出,不如限制输入? -
@BrentWashburne 是的,我认为在此示例中您可以设置
s3 = ['c'],但在实际应用中存在更复杂的约束,其中无法先验消除输入。例如,如果有一个限制,即只允许两个连续的相同字母(例如,'cc'、'dd'、'ee、'ff') -
在这种情况下,
s2 = s3 = ['c'],然后是s2 = s3 = ['d'],依此类推。我的观点是,您可以通过智能输入而不是过滤所有可能的组合来真正加快速度,因为您知道其中许多组合是未使用的。如果一切都失败了,请使用过滤器。
标签: python algorithm combinatorics