Python 3.x 在Python3中创建分层组合?

Python 3.x 在Python3中创建分层组合?,python-3.x,combinations,itertools,Python 3.x,Combinations,Itertools,我有一个有趣的问题。我有一个分层数据列表 relation = [('grandfather'), ('father'), ('son')] 从这个意义上讲,它是分层的,没有祖父,就不可能有儿子,但是没有儿子,就可能有父亲 每个条目都可以有一个状态 status = [('tall'), ('short')] 我试图找到所有可能的组合,这是有意义的。这就是组合 combination_sense = [('grandfather', 'tall'), ('father', 'short'),

我有一个有趣的问题。我有一个分层数据列表

relation = [('grandfather'), ('father'), ('son')]
从这个意义上讲,它是分层的,没有祖父,就不可能有儿子,但是没有儿子,就可能有父亲

每个条目都可以有一个状态

status = [('tall'), ('short')]
我试图找到所有可能的组合,这是有意义的。这就是组合

combination_sense = [('grandfather', 'tall'), ('father', 'short'), ('son', 'short')]
combination_no_sense  = [('grandfather', 'tall'), ('son', 'short')]
可能存在,但组合

combination_sense = [('grandfather', 'tall'), ('father', 'short'), ('son', 'short')]
combination_no_sense  = [('grandfather', 'tall'), ('son', 'short')]
可能不存在,因为没有父亲就不可能有儿子

同样,联合

combination_sense = [('grandfather', 'tall'), ('father', 'short')]
可能确实存在

我用
itertools
试了试。我尝试了
list(itertools.product())
itertools.permutations()
,但至今无法正常工作


如何处理层次关系?

如果我理解正确,您希望从两个列表中生成所有值的组合,但您对待列表的方式不同

对于第一个层次列表,必须始终使用第一个值,并且可以将值序列扩展任意数量,只要不跳过任何值。因此,对于您的示例列表,您将生成
['grander']、['grander'、'father']、['grander'、'father']、['grander'、'father'、'son']

对于第二个列表,您希望所有组合(带替换)的长度与您要与之配对的层次结构值相同

使用自定义生成器函数应该不难做到这一点:

import itertools as it

def combine(relations, statuses):
    for i in range(len(relations)):
        relation = relations[:i+1]
        for status_combination in it.product(statuses, repeat=i+1):
            yield list(zip(relation, status_combination))
这首先从较小的结果开始(例如,那些只有
“祖父”
)的结果)。如果您想从最长的实例(包括
'son'
)开始,您可以将上述代码中
i+1
的两个实例都替换为
len(relations)-i

如果您想要
关系的所有连续子序列
(因此
['father'、'son']
将被允许,就像
['father']
['son']
本身一样),您只需做一些更改即可获得该结果:

import itertools as it

def combine(relations, statuses):
    for start, stop in it.combinations(range(len(relations) + 1), 2): # get two indexes
        relation = relations[start:stop]                              # slice using both
        for status_combination in it.product(statuses, repeat=stop-start): # use difference
            yield list(zip(relation, status_combination))

这个版本产生了更多的连续生成的可能性,这是我从我们的对话中了解到的。我不知道这是否是你真正想要的

from itertools import product

relations = ['grandfather', 'father', 'son']
statuses = ['tall', 'short']

possibilities = []
for per in range(1,4):
    contiguous_relations = [relations[i: i+per] for i in range(-per+1+len(relations))]
    possibilities.extend(contiguous_relations)

for possibility in possibilities:
    print('---', possibility)
    for p in product(statuses, repeat=len(possibility)):
        print (list(zip(possibility, p)))
结果:

--- ['grandfather']
[('grandfather', 'tall')]
[('grandfather', 'short')]
--- ['father']
[('father', 'tall')]
[('father', 'short')]
--- ['son']
[('son', 'tall')]
[('son', 'short')]
--- ['grandfather', 'father']
[('grandfather', 'tall'), ('father', 'tall')]
[('grandfather', 'tall'), ('father', 'short')]
[('grandfather', 'short'), ('father', 'tall')]
[('grandfather', 'short'), ('father', 'short')]
--- ['father', 'son']
[('father', 'tall'), ('son', 'tall')]
[('father', 'tall'), ('son', 'short')]
[('father', 'short'), ('son', 'tall')]
[('father', 'short'), ('son', 'short')]
--- ['grandfather', 'father', 'son']
[('grandfather', 'tall'), ('father', 'tall'), ('son', 'tall')]
[('grandfather', 'tall'), ('father', 'tall'), ('son', 'short')]
[('grandfather', 'tall'), ('father', 'short'), ('son', 'tall')]
[('grandfather', 'tall'), ('father', 'short'), ('son', 'short')]
[('grandfather', 'short'), ('father', 'tall'), ('son', 'tall')]
[('grandfather', 'short'), ('father', 'tall'), ('son', 'short')]
[('grandfather', 'short'), ('father', 'short'), ('son', 'tall')]
[('grandfather', 'short'), ('father', 'short'), ('son', 'short')]

你能给我们看看你的实际数据吗?或者至少是一个样本?请告诉我您何时/是否这样做。@BillBell我得到的数据完全如图所示,即两个简单的列表。这是显示父子关系的植物学数据。列表上的最后一项总是最年轻的。这种状态实际上是简单明了的。我理解“它是分层的…”意味着许多可能性:
[(“祖父”),(“父亲”),(“儿子”)
[(“祖父”),(“父亲”)]
。也许我明白了。世代必须是连续的:必须有中间的世代(当然!)。允许两个连续的代。允许一代人吗?每个所谓的“状态”都可以应用于列表中的任何一代人?@BillBell,没错!每一代人可能矮,也可能高。允许单代。谢谢你的澄清!非常感谢你。这使我的问题比我想的更进一步!不客气。有趣的问题,而且它们不经常出现。嗨,回答得很好!一个后续问题。如何访问生成器/将其转换为列表?编辑:我的意思是作为函数的一部分?如果要单独操作每个组合,可以使用
for
语句(
for combine in combine(…):
)循环生成器,或者将其传递给
list
构造函数(
results=list(combine(…)
),它将让您一起查看所有组合。