【问题标题】:Combinations of items in a list using specific critera使用特定标准的列表中的项目组合
【发布时间】:2021-11-04 18:35:30
【问题描述】:

我正在尝试在列表中查找特定的项目组合。该列表由重复 y 次的 x 组组成。在这个例子中 x 和 y = 3,但实际上可能更大。我想找到组和 y 的每个组合,但不为给定组合复制 x 值。我认为只展示我想要的示例会更容易。

这是一个例子。

A = ['ST1_0.245', 'ST1_0.29', 'ST1_0.335', 'ST2_0.245', 'ST2_0.29', 'ST2_0.335', 'ST3_0.245', 'ST3_0.29', 'ST3_0.335']

所以三个组,ST1、ST2 和 ST3——每个组有 3 次迭代,0.245、0.290 和 0.335。

我想找到以下组合。

('ST1_0.245', 'ST2_0.245', 'ST3_0.245')
('ST1_0.245', 'ST2_0.245', 'ST3_0.29')
('ST1_0.245', 'ST2_0.245', 'ST3_0.335')
('ST1_0.245', 'ST2_0.29', 'ST3_0.245')
('ST1_0.245', 'ST2_0.29', 'ST3_0.29')
('ST1_0.245', 'ST2_0.29', 'ST3_0.335')
('ST1_0.245', 'ST2_0.335', 'ST3_0.245')
('ST1_0.245', 'ST2_0.335', 'ST3_0.29')
('ST1_0.245', 'ST2_0.335', 'ST3_0.335')
('ST1_0.29', 'ST2_0.245', 'ST3_0.245')
('ST1_0.29', 'ST2_0.245', 'ST3_0.29')
('ST1_0.29', 'ST2_0.245', 'ST3_0.335')
('ST1_0.29', 'ST2_0.29', 'ST3_0.245')
('ST1_0.29', 'ST2_0.29', 'ST3_0.29')
('ST1_0.29', 'ST2_0.29', 'ST3_0.335')
('ST1_0.29', 'ST2_0.335', 'ST3_0.245')
('ST1_0.29', 'ST2_0.335', 'ST3_0.29')
('ST1_0.29', 'ST2_0.335', 'ST3_0.335')
('ST1_0.335', 'ST2_0.245', 'ST3_0.245')
('ST1_0.335', 'ST2_0.245', 'ST3_0.29')
('ST1_0.335', 'ST2_0.245', 'ST3_0.335')
('ST1_0.335', 'ST2_0.29', 'ST3_0.245')
('ST1_0.335', 'ST2_0.29', 'ST3_0.29')
('ST1_0.335', 'ST2_0.29', 'ST3_0.335')
('ST1_0.335', 'ST2_0.335', 'ST3_0.245')
('ST1_0.335', 'ST2_0.335', 'ST3_0.29')
('ST1_0.335', 'ST2_0.335', 'ST3_0.335')

请注意,ST1、ST2 和 ST3 在每个组合中仅出现一次。

这是我至少要在小案例中使用的代码。

import itertools
import numpy as np

comb = []
gr_list=['ST1','ST2','ST3']
for itr in itertools.combinations(A, len(gr_list)):
    # pdb.set_trace()
    for n in np.arange(len(gr_list)):
        if sum(itr[n].split('_')[0] in s for s in itr) > 1:
            break
    
    if n == len(gr_list)-1:
        comb.append(itr)

这适用于我测试的几个小示例,但是当我尝试更大的值时,我得到的结果比我想象的要多,但这可能是我尝试计算预期数量时的错误。但无论哪种方式,都需要很长时间。有没有更快的方法来做到这一点?

我确实分别拥有这两个值。在我写这篇文章时,我觉得这是一种更好的方法,但我也不知道该怎么做。

【问题讨论】:

  • “我得到的结果比我想象的要多”-在您的示例中,第一个值有 3 个选择乘以第二个值有 3 个选择,最后一个值有 3 个选择,即 3x3x3 = 27 . 所以是的,输出的大小会很快变得非常大。你打算用这样的输出做什么?

标签: python itertools


【解决方案1】:

根据需要创建组,然后在组上使用itertools.product

A = ['ST1_0.245', 'ST1_0.29', 'ST1_0.335', 
     'ST2_0.245', 'ST2_0.29', 'ST2_0.335', 
     'ST3_0.245', 'ST3_0.29', 'ST3_0.335']

prefixes = set(s.split("_")[0] for s in A)
groups = [[a for a in A if a.split("_")[0]==p] for p in prefixes]

>>> list(itertools.product(*groups))

[('ST2_0.245', 'ST3_0.245', 'ST1_0.245'),
 ('ST2_0.245', 'ST3_0.245', 'ST1_0.29'),
 ('ST2_0.245', 'ST3_0.245', 'ST1_0.335'),
 ('ST2_0.245', 'ST3_0.29', 'ST1_0.245'),
 ('ST2_0.245', 'ST3_0.29', 'ST1_0.29'),
 ('ST2_0.245', 'ST3_0.29', 'ST1_0.335'),
 ('ST2_0.245', 'ST3_0.335', 'ST1_0.245'),
 ('ST2_0.245', 'ST3_0.335', 'ST1_0.29'),
 ('ST2_0.245', 'ST3_0.335', 'ST1_0.335'),
 ('ST2_0.29', 'ST3_0.245', 'ST1_0.245'),
 ('ST2_0.29', 'ST3_0.245', 'ST1_0.29'),
 ('ST2_0.29', 'ST3_0.245', 'ST1_0.335'),
 ('ST2_0.29', 'ST3_0.29', 'ST1_0.245'),
 ('ST2_0.29', 'ST3_0.29', 'ST1_0.29'),
 ('ST2_0.29', 'ST3_0.29', 'ST1_0.335'),
 ('ST2_0.29', 'ST3_0.335', 'ST1_0.245'),
 ('ST2_0.29', 'ST3_0.335', 'ST1_0.29'),
 ('ST2_0.29', 'ST3_0.335', 'ST1_0.335'),
 ('ST2_0.335', 'ST3_0.245', 'ST1_0.245'),
 ('ST2_0.335', 'ST3_0.245', 'ST1_0.29'),
 ('ST2_0.335', 'ST3_0.245', 'ST1_0.335'),
 ('ST2_0.335', 'ST3_0.29', 'ST1_0.245'),
 ('ST2_0.335', 'ST3_0.29', 'ST1_0.29'),
 ('ST2_0.335', 'ST3_0.29', 'ST1_0.335'),
 ('ST2_0.335', 'ST3_0.335', 'ST1_0.245'),
 ('ST2_0.335', 'ST3_0.335', 'ST1_0.29'),
 ('ST2_0.335', 'ST3_0.335', 'ST1_0.335')]

【讨论】:

  • 谢谢!发布此消息后,我越来越近了,但我认为没有帮助我不会得到它。你能解释一下 *groups 在做什么吗?
  • 查找iterable unpacking。 SO上有很多问题可以解决这个问题。 Here's 一个。
【解决方案2】:

您可以为此使用itertools.product,这将产生一个迭代器而不是一个列表(如果您是迭代而不是产生整个集合,这通常会更有效)。您最终将得到不同类别长度的乘积作为迭代器中元素的数量。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-06
    • 2013-05-01
    • 2012-07-11
    • 1970-01-01
    • 2021-10-14
    相关资源
    最近更新 更多