带有可选列表的笛卡尔积
Cartesian Product with optional lists
我正在 python 创建一个程序,它允许我根据给定的资产生成 NFT 艺术。
显然,可以生成的艺术数量根据资产(图层和图层图像)而变化,这正是问题所在,我如何计算可能的组合并计算可选图层?
更清楚:
例如我有4层:
l1 = ["A","B"]
l2 = ["C"]
l3 = ["D","E"] #optional
l4 = ["F","G"] #optional
其中 l3 和 l4 是可选的。所以我期望的组合是:
1. ["A","C"]
2. ["B","C"]
3. ["A","C","D"]
4. ["A","C","E"]
5. ["B","C","D"]
6. ["B","C","E"]
7. ["A","C","F"]
8. ["A","C","G"]
9. ["B","C","F"]
10. ["B","C","G"]
11. ["A","C","D","F"]
12. ["A","C","D","G"]
13. ["A","C","E","F"]
14. ["A","C","E","G"]
15. ["B","C","D","F"]
16. ["B","C","D","G"]
17. ["B","C","E","F"]
18. ["B","C","E","G"]
我怎样才能做到这一点?我尝试使用 itertools.product
但显然它考虑了所有列表
我假设可选层的顺序很重要,因此您可以迭代创建可选层的所有组合,然后在 layers
+ optional_layers
上使用 itertools.product
生成列表。
import itertools
from pprint import pprint
l1 = ["A","B"]
l2 = ["C"]
l3 = ["D","E"] #optional
l4 = ["F","G"] #optional
layers = [l1, l2]
optional_layers = [l3, l4]
results = []
results += itertools.product(*layers)
for i in range(len(optional_layers) + 1):
comb = itertools.combinations(optional_layers, r=i)
for c in comb:
results += itertools.product(*layers, *c)
pprint(results)
输出
[('A', 'C'),
('B', 'C'),
('A', 'C'),
('B', 'C'),
('A', 'C', 'D'),
('A', 'C', 'E'),
('B', 'C', 'D'),
('B', 'C', 'E'),
('A', 'C', 'F'),
('A', 'C', 'G'),
('B', 'C', 'F'),
('B', 'C', 'G'),
('A', 'C', 'D', 'F'),
('A', 'C', 'D', 'G'),
('A', 'C', 'E', 'F'),
('A', 'C', 'E', 'G'),
('B', 'C', 'D', 'F'),
('B', 'C', 'D', 'G'),
('B', 'C', 'E', 'F'),
('B', 'C', 'E', 'G')]
一种方法是使用 itertools docs 中的 powerset
配方。将 'required lists' 的乘积与 'optional-list-set' 的每个子集链接在一起,生成一个生成每种可能性一次的生成器:
def powerset(iterable):
"""powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"""
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
def product_with_optional(required_sequences, optional_sequences):
return chain.from_iterable(product(*required_sequences, *optionals)
for optionals in powerset(optional_sequences))
optional_combinations = product_with_optional(required_sequences=[l1, l2],
optional_sequences=[l3, l4])
给出:
1 ('A', 'C')
2 ('B', 'C')
3 ('A', 'C', 'D')
4 ('A', 'C', 'E')
5 ('B', 'C', 'D')
6 ('B', 'C', 'E')
7 ('A', 'C', 'F')
8 ('A', 'C', 'G')
9 ('B', 'C', 'F')
10 ('B', 'C', 'G')
11 ('A', 'C', 'D', 'F')
12 ('A', 'C', 'D', 'G')
13 ('A', 'C', 'E', 'F')
14 ('A', 'C', 'E', 'G')
15 ('B', 'C', 'D', 'F')
16 ('B', 'C', 'D', 'G')
17 ('B', 'C', 'E', 'F')
18 ('B', 'C', 'E', 'G')
我正在 python 创建一个程序,它允许我根据给定的资产生成 NFT 艺术。 显然,可以生成的艺术数量根据资产(图层和图层图像)而变化,这正是问题所在,我如何计算可能的组合并计算可选图层?
更清楚:
例如我有4层:
l1 = ["A","B"]
l2 = ["C"]
l3 = ["D","E"] #optional
l4 = ["F","G"] #optional
其中 l3 和 l4 是可选的。所以我期望的组合是:
1. ["A","C"]
2. ["B","C"]
3. ["A","C","D"]
4. ["A","C","E"]
5. ["B","C","D"]
6. ["B","C","E"]
7. ["A","C","F"]
8. ["A","C","G"]
9. ["B","C","F"]
10. ["B","C","G"]
11. ["A","C","D","F"]
12. ["A","C","D","G"]
13. ["A","C","E","F"]
14. ["A","C","E","G"]
15. ["B","C","D","F"]
16. ["B","C","D","G"]
17. ["B","C","E","F"]
18. ["B","C","E","G"]
我怎样才能做到这一点?我尝试使用 itertools.product
但显然它考虑了所有列表
我假设可选层的顺序很重要,因此您可以迭代创建可选层的所有组合,然后在 layers
+ optional_layers
上使用 itertools.product
生成列表。
import itertools
from pprint import pprint
l1 = ["A","B"]
l2 = ["C"]
l3 = ["D","E"] #optional
l4 = ["F","G"] #optional
layers = [l1, l2]
optional_layers = [l3, l4]
results = []
results += itertools.product(*layers)
for i in range(len(optional_layers) + 1):
comb = itertools.combinations(optional_layers, r=i)
for c in comb:
results += itertools.product(*layers, *c)
pprint(results)
输出
[('A', 'C'),
('B', 'C'),
('A', 'C'),
('B', 'C'),
('A', 'C', 'D'),
('A', 'C', 'E'),
('B', 'C', 'D'),
('B', 'C', 'E'),
('A', 'C', 'F'),
('A', 'C', 'G'),
('B', 'C', 'F'),
('B', 'C', 'G'),
('A', 'C', 'D', 'F'),
('A', 'C', 'D', 'G'),
('A', 'C', 'E', 'F'),
('A', 'C', 'E', 'G'),
('B', 'C', 'D', 'F'),
('B', 'C', 'D', 'G'),
('B', 'C', 'E', 'F'),
('B', 'C', 'E', 'G')]
一种方法是使用 itertools docs 中的 powerset
配方。将 'required lists' 的乘积与 'optional-list-set' 的每个子集链接在一起,生成一个生成每种可能性一次的生成器:
def powerset(iterable):
"""powerset([1,2,3]) --> () (1,) (2,) (3,) (1,2) (1,3) (2,3) (1,2,3)"""
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s) + 1))
def product_with_optional(required_sequences, optional_sequences):
return chain.from_iterable(product(*required_sequences, *optionals)
for optionals in powerset(optional_sequences))
optional_combinations = product_with_optional(required_sequences=[l1, l2],
optional_sequences=[l3, l4])
给出:
1 ('A', 'C')
2 ('B', 'C')
3 ('A', 'C', 'D')
4 ('A', 'C', 'E')
5 ('B', 'C', 'D')
6 ('B', 'C', 'E')
7 ('A', 'C', 'F')
8 ('A', 'C', 'G')
9 ('B', 'C', 'F')
10 ('B', 'C', 'G')
11 ('A', 'C', 'D', 'F')
12 ('A', 'C', 'D', 'G')
13 ('A', 'C', 'E', 'F')
14 ('A', 'C', 'E', 'G')
15 ('B', 'C', 'D', 'F')
16 ('B', 'C', 'D', 'G')
17 ('B', 'C', 'E', 'F')
18 ('B', 'C', 'E', 'G')