簡體   English   中英

當組的長度已知時,從列表中形成 2、3、4 組的所有可能組合

[英]Form all possible combinations of groups of 2, 3, 4 from a list when the length of groups is known

假設我有像(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嗎?

您可以使用組合,但您仍然必須為組分區實現自己的邏輯:

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

output:

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

[編輯]迭代版本。 使用 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

output:

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

假設原始列表不包含重復的數字,那么

l = {1,2,3,4,5}

[(i,j) for i in itertools.combinations(l,2) for j in itertools.combinations(l.difference(i),3)]
[((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))]

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM