【问题标题】:Python combination of 2 lists (1 repeat, 1 non-repeat)2 个列表的 Python 组合(1 个重复,1 个不重复)
【发布时间】:2013-07-19 00:25:25
【问题描述】:

找到 2 个列表中的值可以重复而另一个列表中的值不能重复的所有组合的最佳方法是什么?现在,我可以得到重复列表的所有组合,如下所示:

import itertools
rep = ['A','B','C', 'D']
norep = ['1','2','3','4']
for i in itertools.combinations_with_replacement(rep,4):
    print i

我可以得到不重复列表的所有组合:

for i in itertool.combinations(norep,4):
    print i

我可以得到两个列表的组合,就好像它们都是非重复的:

for i in itertools.product([0, 1], repeat=4):
    print [(norep[j] if i else rep[j]) for j, i in enumerate(i)]

但是,我不知道如何获得重复列表和非重复列表的组合。我还想添加包括空值在内的组合,例如['A','1',Null]。

【问题讨论】:

  • 每个组合是否应该从第一个列表中抽取一个固定数量的n 值,从第二个列表中抽取一个固定数量的m,分别有重复和不重复?或者你想从一个组合池中绘制一个n 值,允许重复一个列表中的元素,但不允许另一个列表中的元素?
  • 注意:您的“两个列表的组合好像它们都是非重复的”代码不起作用。它永远不会从两个列表中绘制前 2 个元素。
  • @user2357112 感谢您的检查。我没有注意到我的两个列表的组合并没有产生所有的组合。在你的第一篇文章中,我想要后一种行为。我想指定组合中的值的数量,例如n=4 给出 [A,B,1,2] 等或 n=5 给出 [A,C,1,3,null] 等。
  • 是否允许多个Nones? (您更喜欢包含Nones 的元组,还是更短的元组?)
  • @user2357112 我想允许多个“无”并希望它们在元组中。我曾考虑将它们添加到“rep”和“norep”中,但不确定这是否会产生所需的行为。

标签: python python-2.7 combinations product itertools


【解决方案1】:

这就是我得到的。非常接近你的:

from itertools import chain
from itertools import combinations
# Huge name!
from itertools import combinations_with_replacement as cwr
from itertools import starmap
from itertools import product

from operator import add

def _weird_combinations(rep, no_rep, n_from_rep, n_from_norep):
    return starmap(add, product(cwr(rep, n_from_rep),
                                combinations(no_rep, n_from_norep)))

def weird_combinations(rep, no_rep, n):
    rep, no_rep = list(rep), list(no_rep)

    # Allow Nones in the output to represent drawing less than n elements.
    # If either input has None in it, this will be confusing.
    rep.append(None)

    # We can't draw more elements from no_rep than it has.
    # However, we can draw as many from rep as we want.
    least_from_rep = max(0, n-len(no_rep))
    return chain.from_iterable(
            _weird_combinations(rep, no_rep, n_from_rep, n-n_from_rep)
            for n_from_rep in xrange(least_from_rep, n+1))

【讨论】:

    【解决方案2】:

    我想我已经想出了一个解决方案,但如果有错误请纠正我。我也很想看看是否有更优雅的解决方案。

    首先,我想出了组合的总数。所有没有替换的组合都等于 n!/r!(n-r)!并且替换等于 (m+s-1)!/s!(m-1)!其中 m 和 n 是可供选择的项目数,r 和 s 是您实际选择的项目数。因为我知道每个组合中我想要的总项目(我们称之为上限),我找到了无替换类型(n = 0)的 0 和替换类型的“上限”(m = 3)的组合数并将这些数字相乘。然后,将无替换类型 (n=1) 的 1 的组合数乘以替换类型 (m=2) 的组合“cap-1”。这样做直到您最终添加了无替换类型(n = 3)乘以替换类型(m = 0)的“上限”的组合(感谢@André Nicolas)。组合数代码如下。

    import itertools
    from math import factorial as fact
    norep = ['A','B','C']
    rep = ['1','2','3']
    
    cap = 3     #length of combinations, e.g. cap=3, combo1=123,combo2=A12,etc
    combos = 0
    
    for i in range(cap+1):
        combnorep = fact(len(norep))/(fact(cap-i)*fact(len(norep)-(cap-i)))
        combrep = fact(len(rep)+i-1)/(fact(i)*fact(len(rep)-1))
        combos = combos + combnorep*combrep
    print combos
    

    对于本例,组合数为 38。接下来,我想打印所有组合。为此,我确定了所有替换、所有无替换以及两者的任意组合的组合,例如n=0,m=3;n=1,m=2;等等。这是我想出的:

    for i in range(cap+1):
        norepcomb = [j for j in itertools.combinations(norep,i)]
        repcomb = [k for k in itertools.combinations_with_replacement(rep,cap-i)]
        for l in itertools.product(norepcomb,repcomb):
            print list(itertools.chain.from_iterable(l))
    

    要包含none,我只需将none 包含在我的列表中以用于替换组合。我希望对此有任何反馈,特别是如果有更好的解决方案或者这不像我认为的那样有效。谢谢!

    【讨论】:

    • 这与我在无聊并转而玩一些视频游戏之前所做的非常接近。您不需要其中的一些列表推导,并且我的代码产生了不同的输出格式。我想我的工作标签仍然处于打开状态。
    猜你喜欢
    • 1970-01-01
    • 2019-08-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-20
    • 2019-02-08
    • 2023-03-14
    • 2018-04-27
    相关资源
    最近更新 更多