[英]Combination of N elements in L groups of K items in python
給定一個包含 N 個元素的列表,例如
mylist = [0, 1, 2, 3, 4, 5, 6, 7]
我想找到 L 組中 K 元素的所有組合,例如對於K=4
, L=2
,結果為
L=0 L=1
1) [0, 1, 2, 3] [4, 5, 6, 7]
2) [0, 1, 2, 4] [3, 5, 6, 7]
3) [0, 1, 2, 5] [3, 4, 6, 7]
... etc...
69) [4, 5, 6, 7] [0, 1, 2, 3]
請注意, [0, 1, 2, 3]
和[0, 1, 3, 2]
將被視為第一組的相同組合。
對於L=2
的情況,我使用以下
from itertools import combinations
N = 8
M = 4
L = N // M
combs = list(combinations(range(N), M))
allidx = list(range(N))
for c, comb in enumerate(combs):
idx1 = list(comb)
idx2 = list(set(allidx) - set(idx1))
print(c, idx1,'\t',idx2)
首先,這種“組合”的數學定義是什么?
其次,在L>2
的情況下,是否有比計算所有排列並在之后修剪它們更有效的方法來計算它們?
您可以使用遞歸函數,從列表中獲取k
元素的所有組合,並將它們與其余元素的組合組合。
import itertools
def combs(lst, k, l):
if l == 0:
yield []
else:
for c in itertools.combinations(lst, k):
rest = [x for x in lst if x not in c]
for res in combs(rest, k, l-1):
yield [c, *res]
mylist = [0, 1, 2, 3, 4, 5, 6, 7]
for res in combs(mylist, 4, 2):
print(res)
在這里,部分rest = [x for x in lst if x not in c]
僅在列表中的元素是唯一的情況下才有效。 如果可以有重復的元素,您可以改為只獲取索引的組合,例如像這樣(其余部分保持不變):
for idc in itertools.combinations(range(len(lst)), k):
comb = [lst[i] for i in idc]
idc_set = set(idc)
rest = [x for i, x in enumerate(lst) if i not in idc_set]
for res in combs(rest, k, l-1):
yield [comb, *res]
(另外,這里假設lst
至少有l*k
元素。)
這是從長度為 n 的集合中生成所有大小為 k 的唯一分區的方法。
此類分區的數量是(p 是零件的數量,等於您的 L):
NPK(n,k) = n! / ((k!)^p * p!)
並且增長很快(n=9,k=3 時為 280)。
算法以遞歸方式將項目分布到各個部分。 為了避免重復生成相同的分區(如01 23 45
和01 45 23
),我們應該限制每個組的前導(最小)元素的位置。
在這里,我使用lastfilled
參數作為最右邊填充部分的索引,因此項目 0 始終屬於第 0 部分,項目 1 可能屬於第 0 部分或第 1 部分,但不屬於第 2 部分,依此類推。 有了中間結果01 __ __
我們只能在下一級得到01 2_ __
,而不是01 __ 2_
。
def genp(l, parts, cnts, n, k, p, m, lastfilled):
if m == n:
l.append(parts[:])
return
for i in range(min(p, lastfilled + 2)):
if cnts[i] < k:
parts[i][cnts[i]] = m
cnts[i] += 1
genp(l, parts, cnts, n, k, p, m+1, max(i, lastfilled))
cnts[i] -= 1
def genpartssizek(n, k):
l = []
p = n // k
parts = [[0]*k for _ in range(p)]
cnts = [0]*p
genp(l, parts, cnts, n, k, p, 0, -1)
return l
print(genpartssizek(6,2))
[[[0, 1], [2, 3], [4, 5]],
[[0, 1], [2, 4], [3, 5]],
[[0, 1], [2, 5], [3, 4]],
[[0, 2], [1, 3], [4, 5]],
[[0, 2], [1, 4], [3, 5]],
[[0, 2], [1, 5], [3, 4]],
[[0, 3], [1, 2], [4, 5]],
[[0, 4], [1, 2], [3, 5]],
[[0, 5], [1, 2], [3, 4]],
[[0, 3], [1, 4], [2, 5]],
[[0, 3], [1, 5], [2, 4]],
[[0, 4], [1, 3], [2, 5]],
[[0, 5], [1, 3], [2, 4]],
[[0, 4], [1, 5], [2, 3]],
[[0, 5], [1, 4], [2, 3]]]
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.