我找到了列出以k个元素组分组的n个元素的所有可能组合的方法。从数学来看,数字很简单:n!/(k!*(n-k)!)和python代码使用itertools非常简单:
>>> import itertools
>>> a = [1,2,3,4]
>>> list(itertools.combinations(a,3))
[(1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4)]
但是如何实现限制:仅列出只有m个元素的组?所以在前面的例子中,对于m = 1,结果应为:
[(1, 2, 3)]
有5个元素,m = 1:
>>> b=[1,2,3,4,5]
>>> list(itertools.combinations(b,3))
[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 3, 4), (1, 3, 5), (1, 4, 5), (2, 3, 4), (2, 3, 5), (2, 4, 5), (3, 4, 5)]
所以我的结果是:
[(1, 2, 3), (1, 4, 5)]
这个问题的实际应用是如何对人进行分组,考虑到只有m个人可以在结果组中重复。想法是找到不同人群,避免群体的“朋友”。想象一下学校活动,重复几天,我们希望尽可能避免人们与他人重复。
答案 0 :(得分:1)
可以使用for
循环来比较第一个组合与休息(使用集合交集函数"&"
):
def getsets(a, n): # FUNCTION FOR THIS PURPOSE
combos = list(itertools.combinations(a,n)) # GET ALL COMBINATIONS
print(combos[0]) # PRINT FIRST COMBINATION
for i in combos[1:]: # FOR EACH OF REST
if len(set(combos[0]) & set(i)) == 1: # IF ONLY 1 ITEM COMMON WITH INITIAL
print(i) # PRINT IT
测试:
getsets([1,2,3,4], 3)
print("---------")
getsets([1,2,3,4,5], 3)
输出:
(1, 2, 3) # INITIAL SET ONLY
---------
(1, 2, 3) # INITIAL SET
(1, 4, 5) # ONLY '1' IS COMMON WITH FIRST SET
(2, 4, 5) # ONLY '2' IS COMMON WITH FIRST SET
(3, 4, 5) # ONLY '3' IS COMMON WITH FIRST SET
{1, 2, 3} # ONLY '4' IS COMMON WITH FIRST SET
答案 1 :(得分:0)
您可以使用for
循环:
m = 1
combos = list(itertools.combinations(a,3))
result = []
for combo in combos:
if result:
if all([sum([1 for item in combo if item in tup]) == 1 for tup in result]):
result.append(combo)
else:
result.append(combo)
result
#[(1, 2, 3), (1, 4, 5)]
通过这种方式,您将能够控制共有成员的数量并获得所需的输出。
答案 2 :(得分:0)
似乎是,您获得的结果的逻辑等价物是这样的:
class User(models.Model):
first_name = models.CharField(max_length=20)
last_name = models.CharField(max_length=20)
email_address = models.EmailField(max_length=50, unique=True)
def __str__(self):
return self.first_name
在您的示例中,元组不会与其他任何可用元素共享超过m个共同元素。但正如它在评论中指出的那样,该解决方案严格按照操作顺序进行。第一个元组确定下一个元组是可以接受的。
请注意,您在评论中所说的内容是一个更广泛的问题:将a = range(1,6)
shared_elem_count = 1
group_count = 3
combinations = itertools.combinations(a, group_count)
results = []
for combination in combinations:
res_union = set().union(*results)
intersection = set(combination).intersection(res_union)
if len(intersection) <= shared_elem_count:
results.append(combination)
人分组为n
组,但不超过{{1}人们的共同点将提供比我们没有过滤掉的解决方案更多的解决方案&#39;。例如,您已指出k
和m
解决方案是:
m = 1
...但实际上还有更多解决方案,例如:
a = (1,2,3,4,5)
所以我不能完全确定过滤组合是否是解决问题的正确方法(尽管如此, 实际上你想要实现的目标 ,谁知道)。