在Python 3中创建分层组合?

时间:2018-01-25 18:19:18

标签: python-3.x combinations itertools

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

relation = [('grandfather'), ('father'), ('son')]

从某种意义上说,如果没有son就不能有grandfather,但father可能没有son

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

status = [('tall'), ('short')]

我试图找到所有可能的组合,这是有道理的。这就是组合

combination_sense = [('grandfather', 'tall'), ('father', 'short'), ('son', 'short')]

可能存在,但组合

combination_no_sense  = [('grandfather', 'tall'), ('son', 'short')]

可能不存在,因为son没有father

同样,组合

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

我用itertools尝试了自己。我尝试了list(itertools.product())itertools.permutations(),但我无法使其正常工作。

如何处理层次关系?帮助非常有用!

2 个答案:

答案 0 :(得分:2)

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

对于第一个分层列表,您必须始终使用第一个值,并且只要您不跳过任何值,就可以将值序列扩展任何数量。因此,对于您的示例列表,您将生成['grandfather'], ['grandfather', 'father'], ['grandfather', '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))

首先从较小的结果开始(例如仅包含'grandfather'的结果)。如果您想从最长的(包含'son'的那些)开始,您可以将上面代码中的i+1的两个实例替换为len(relations)-i

如果您想要relations的所有连续子序列(因此['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))

答案 1 :(得分:1)

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

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