带有可选列表的笛卡尔积

发布于 2025-01-10 21:43:46 字数 727 浏览 4 评论 0原文

我正在用 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 但显然它考虑了所有列表

I am creating a program, in python, that allows me to generate NFT Art based on the given assets.
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:

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

where l3 and l4 are optional. 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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

壹場煙雨 2025-01-17 21:43:46

一种方法是使用 itertools 文档。将“必需列表”的乘积与“可选列表集”的每个子集链接在一起给出一个生成器,该生成器生成每种可能性一次:

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

One way to do this is with the powerset recipe from the itertools docs. 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')
呢古 2025-01-17 21:43:46

我假设可选层的顺序很重要,因此您可以迭代地创建可选层的所有组合,然后在 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)

输出

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

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.

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

[('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')]
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文