简体   繁体   English

带有可选列表的笛卡尔积

[英]Cartesian Product with optional lists

I am creating a program, in python, that allows me to generate NFT Art based on the given assets.我正在 python 中创建一个程序,它允许我根据给定的资产生成 NFT 艺术。 Obviously the number of arts that can be generated varies according to the assets (layers and layer images) and this is precisely the problem, how can I calculate the possible combinations also counting the optional layers?显然,可以生成的艺术数量根据资产(图层和图层图像)而变化,这正是问题所在,我如何计算可能的组合并计算可选图层?

To be clearer:更清楚一点:

for example I have 4 layers:例如我有 4 层:

l1 = ["A","B"]
l2 = ["C"]
l3 = ["D","E"] #optional
l4 = ["F","G"] #optional

where l3 and l4 are optional.其中 l3 和 l4 是可选的。 So the combinations I expect are:所以我期望的组合是:

 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"]

How can I get to that?我怎样才能做到这一点? I tried with itertools.product but obviusly it take into account all lists我尝试使用itertools.product但显然它考虑了所有列表

I'm assuming the ordering of the optional layers matter, so you can just iteratively create all combinations of the optional layers, then use itertools.product on the layers + optional_layers to generate the lists.我假设可选层的顺序很重要,因此您可以迭代创建可选层的所有组合,然后在layers上使用itertools.product + optional_layers来生成列表。

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)

Output Output

[('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')]

One way to do this is with the powerset recipe from the itertools docs .一种方法是使用itertools 文档中的powerset配方。 Chaining together the products of 'required lists' with every subset of the 'optional-list-set' gives a generator that produces each possibility once:将“必需列表”的产品与“可选列表集”的每个子集链接在一起,生成一个生成每种可能性一次的生成器:

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])

which gives:这使:

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')

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM