Python 当组的长度已知时,从列表中形成2、3、4组的所有可能组合

Python 当组的长度已知时,从列表中形成2、3、4组的所有可能组合,python,Python,假设我有类似于(1,2,3,4,5)的元组 我想把它分组为1,1,0,即(1组2),(1组3)和(0组4) 结果将是(1,2)、(3,4,5),(2,3)、(1,4,5),(3,4)、(1,2,5),(4,5)、(1,2,3)(1,3)、(2,4,5)等等 我如何实现这一点?如果原始列表不包含重复的数字,那么使用itertools?是否可以实现这一点 l={1,2,3,4,5} [(i,j)表示itertools中的i.组合(l,2)表示itertools中的j.组合(l.差异(i),3)]

假设我有类似于
(1,2,3,4,5)
的元组

我想把它分组为
1,1,0
,即(1组2),(1组3)和(0组4)

结果将是
(1,2)、(3,4,5)
(2,3)、(1,4,5)
(3,4)、(1,2,5)
(4,5)、(1,2,3)
(1,3)、(2,4,5)
等等


我如何实现这一点?如果原始列表不包含重复的数字,那么使用
itertools

是否可以实现这一点

l={1,2,3,4,5}
[(i,j)表示itertools中的i.组合(l,2)表示itertools中的j.组合(l.差异(i),3)]

您可以使用组合,但仍然必须为组分区实现自己的逻辑:

from itertools import combinations

def group(T,g234):
    if sum(g234) == 0: yield [];return                 # end resursion
    size = next(g for g,n in enumerate(g234,2) if n>0) # first count>0
    g234 = list(g234)                                  # remaining groups
    g234[size-2] -= 1
    for combo in combinations(range(len(T)),size):     # combine tuple indexes
        part   = tuple(T[i] for i in combo)            # subgroup of combination
        others = [v for i,v in enumerate(T) if i not in combo]  # remaining
        yield from ([part]+rest for rest in group(others,g234)) # assemble parts
输出:

print(*group((1,2,3,4,5),[1,1,0]),sep="\n")
[(1, 2), (3, 4, 5)]
[(1, 3), (2, 4, 5)]
[(1, 4), (2, 3, 5)]
[(1, 5), (2, 3, 4)]
[(2, 3), (1, 4, 5)]
[(2, 4), (1, 3, 5)]
[(2, 5), (1, 3, 4)]
[(3, 4), (1, 2, 5)]
[(3, 5), (1, 2, 4)]
[(4, 5), (1, 2, 3)]

print(*group((1,2,3,4,5,6),(0,2,0)),sep="\n")
[(1, 2, 3), (4, 5, 6)]
[(1, 2, 4), (3, 5, 6)]
[(1, 2, 5), (3, 4, 6)]
[(1, 2, 6), (3, 4, 5)]
[(1, 3, 4), (2, 5, 6)]
[(1, 3, 5), (2, 4, 6)]
...

print(*group((1,2,3,4,5,6),(3,0,0)),sep="\n")
[(1, 2), (3, 4), (5, 6)]
[(1, 2), (3, 5), (4, 6)]
[(1, 2), (3, 6), (4, 5)]
[(1, 2), (4, 5), (3, 6)]
[(1, 2), (4, 6), (3, 5)]
[(1, 2), (5, 6), (3, 4)]
...

print(*group((1,2,3,4,5,6,7,8,9),(1,1,1)),sep="\n")
[(1, 2), (3, 4, 5), (6, 7, 8, 9)]
[(1, 2), (3, 4, 6), (5, 7, 8, 9)]
[(1, 2), (3, 4, 7), (5, 6, 8, 9)]
[(1, 2), (3, 4, 8), (5, 6, 7, 9)] 
...
for parts in group(range(1000),(500, 0,0)):
    print(parts[:3],"...",parts[-3:])

[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 997), (998, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 998), (997, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 999), (997, 998)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (997, 998), (996, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (997, 999), (996, 998)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (998, 999), (996, 997)]
...
[编辑]迭代版本。使用deque替换递归的调用堆栈:

from itertools import combinations
from collections import deque
def group(T,g234):
    stack = deque([(T,g234,[],None)]) #tuple, groups, parts, combo_iterator
    while stack:
        T,g234,parts,cIter = stack.pop()
        #print(len(T),g234,len(parts),bool(cIter))
        if cIter is None:
            if not sum(g234): yield parts;continue  # partition complete
            size = next(g for g,n in enumerate(g234,2) if n>0) # first count>0
            g234 = list(g234)                                  # remaining groups
            g234[size-2] -= 1
            cIter = combinations(range(len(T)),size)     # combine tuple indexes
        combo = next(cIter,None)
        if combo is None: continue
        stack.append((T,g234,parts,cIter))
        part   = tuple(T[i] for i in combo)            # subgroup of combination
        others = [v for i,v in enumerate(T) if i not in combo]  # remaining
        stack.append((others,g234,parts+[part],None))           # assemble parts
输出:

print(*group((1,2,3,4,5),[1,1,0]),sep="\n")
[(1, 2), (3, 4, 5)]
[(1, 3), (2, 4, 5)]
[(1, 4), (2, 3, 5)]
[(1, 5), (2, 3, 4)]
[(2, 3), (1, 4, 5)]
[(2, 4), (1, 3, 5)]
[(2, 5), (1, 3, 4)]
[(3, 4), (1, 2, 5)]
[(3, 5), (1, 2, 4)]
[(4, 5), (1, 2, 3)]

print(*group((1,2,3,4,5,6),(0,2,0)),sep="\n")
[(1, 2, 3), (4, 5, 6)]
[(1, 2, 4), (3, 5, 6)]
[(1, 2, 5), (3, 4, 6)]
[(1, 2, 6), (3, 4, 5)]
[(1, 3, 4), (2, 5, 6)]
[(1, 3, 5), (2, 4, 6)]
...

print(*group((1,2,3,4,5,6),(3,0,0)),sep="\n")
[(1, 2), (3, 4), (5, 6)]
[(1, 2), (3, 5), (4, 6)]
[(1, 2), (3, 6), (4, 5)]
[(1, 2), (4, 5), (3, 6)]
[(1, 2), (4, 6), (3, 5)]
[(1, 2), (5, 6), (3, 4)]
...

print(*group((1,2,3,4,5,6,7,8,9),(1,1,1)),sep="\n")
[(1, 2), (3, 4, 5), (6, 7, 8, 9)]
[(1, 2), (3, 4, 6), (5, 7, 8, 9)]
[(1, 2), (3, 4, 7), (5, 6, 8, 9)]
[(1, 2), (3, 4, 8), (5, 6, 7, 9)] 
...
for parts in group(range(1000),(500, 0,0)):
    print(parts[:3],"...",parts[-3:])

[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 997), (998, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 998), (997, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (996, 999), (997, 998)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (997, 998), (996, 999)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (997, 999), (996, 998)]
[(0, 1), (2, 3), (4, 5)] ... [(994, 995), (998, 999), (996, 997)]
...

原始列表是否会包含重复的数字,如1,1,2,3?如何将
1,1,0
翻译成
(1组2)
(1组3)
(0组4)
我不懂110。为什么你不能一人一组,为什么从2开始?例如,5组1组为5000?您希望的输出是多少?每个元素都有两个元组吗?或者它是一个平面列表还是元组?1,1,0是否表示2人组打开,3人组打开,4人组关闭?在这种情况下,
(1组2)、(1组3)和(0组4)
似乎有误导性。@Epsi95否,不会有任何重复值。我会在有时间的时候更新这个问题。阿兰的回答几乎不能说明我的预期产出是什么。你是如何得出这是预期产出的结论的?这个问题似乎很模糊-顺便说一句,我不是。谢谢你的回答。是否可以接受iterable、t2、t3、t4(2、3和4个团队的数量)。类似于
def组(l、t2、t3、t4)
并返回可能的组合?如果t2,t3,t4中的任何一个为零,那么这个解决方案会失败吗?因为我们使用嵌套的,这正是我想要的。但T的长度可能是10万<代码>打印(*组(范围(100000),(50000,0,0)),sep='\n')。因为它超出了最大递归深度,我们能不能有一个相同的非递归解决方案?添加了一个迭代版本,我必须为非常大的尺寸进行优化,但您确实意识到,即使只有500组2,您也会得到10^1059个以上的模式。其中50000个将以指数形式增加(我甚至无法计算)