【问题标题】:Creating hierarchical combinations in Python 3?在 Python 3 中创建层次组合?
【发布时间】:2018-01-25 18:19:17
【问题描述】:

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

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

从某种意义上说,它是分层的,没有grandfather 就不可能有son,但没有son 就可以有father

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

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

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

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

可能存在,但组合

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

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

同样,组合

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

可能确实存在。

我尝试了itertools。我尝试了list(itertools.product())itertools.permutations(),但我无法让它工作到现在。

如何处理层级关系?

【问题讨论】:

  • 你能告诉我们你的实际数据吗?或者至少是一个样本?并让我知道您何时/如果您这样做了。
  • @BillBell 我得到了完全如图所示的数据,即两个简单的列表。这是显示父子关系的植物数据。列表中的最后一个条目总是最年轻的。状态实际上是谈话和简短的。
  • 我理解“它是分层的......”意味着多种可能性:[('grandfather'), ('father'), ('son')][('grandfather'), ('father')]
  • 也许我赶上了。世代必须是连续的:必须有一个中间世代(当然!)。允许两个连续的世代。允许单代吗?每个所谓的“状态”都可以应用于列表中的任何一代?
  • @BillBell 完全正确!每一代都可能是矮的或高的。允许单代。谢谢你的澄清!

标签: python-3.x combinations itertools


【解决方案1】:

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

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

【讨论】:

  • 嗨,很好的答案!一个后续问题。如何访问生成器/将其转换为列表?
  • 编辑:我的意思是作为函数的一部分?
  • 如果您想分别对每个组合进行操作,您可以使用for 语句(for combination in combine(...):)循环使用生成器,或者您可以将其传递给list 构造函数( results = list(combine(...))) 这将让您一起查看所有组合。
【解决方案2】:

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

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

【讨论】:

  • 非常感谢。这让我的问题比我想象的更进一步!
  • 不客气。有趣的问题,而且它们不经常出现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-06-07
  • 2015-01-31
  • 2021-09-02
相关资源
最近更新 更多