如何将一个列表随机分成两个部分

6

我有12个人需要分成两个不同的队伍。我需要做的是为第一个团队随机选择0到11之间的6个数字,对于第二个团队也是同样的方法,但不能有重叠。最有效的方法是什么?

import random

A = random.choice([x for x in range(12)])

B = random.choice([x for x in range(12) if x != A])

C = random.choice([x for x in range(12) if (x != A) and (x != B)])

team1 = random.sample(range(0, 12), 6)
team2 = random.sample(range(0, 12), 6)

这是我到目前为止写的内容。非常感谢您的帮助。


1
你正在将列表的单个元素与整个列表进行比较,因此 if x!=A 始终为真。 - mousetail
1
将随机选择插入到一个集合中,直到其长度为6,这些是A队,其余为B队。或者从[0, 11]中选择一个随机整数,将其移动到其中一个队伍并从剩余人员列表中删除该元素。再次在[0, 10]中执行相同操作。无论您想要分配每个团队的顺序如何,都要执行此操作,直到每次都移动了6个。 - Adirio
2个回答

13

你可以使用 set集合的差集,像这样:

import random

all_players = set(range(12))

team1 =  set(random.sample(all_players, 6))
team2 = all_players - team1

print(team1)
print(team2)

示例输出:

{1, 5, 8, 9, 10, 11}
{0, 2, 3, 4, 6, 7}

1
虽然这是一个相当优雅的解决方案,但我不确定在这里使用set的优势是什么,一个简单的列表推导式就可以用来过滤掉团队A中的成员。 - Adirio
2
速度是关键——对于12个元素来说,这已经无关紧要了——列表可能会更快(并且在内存方面更便宜),但是对于例如10 ** 6个元素,列表推导需要更长的时间。不确定使用集合进行原地洗牌是否比使用集合更快或更慢,但它将更加高效地利用内存 :) - Patrick Artner
@PatrickArtner 在最坏情况下,a - b(其中ab是集合)的复杂度为O(len(a)*len(b))[x for x in a if x not in b]在最坏情况下也有一个O(len(a)*len(b))的复杂度。摊销复杂度可能更有利于集合版本(O(len(a))),但您还必须遍历ab来创建集合。因此,从设计角度来看,使用集合对于玩家来说是非常合理的选择。 - Adirio
1
集合:检查是否在集合中的时间复杂度为O(1),因此远小于O(len(a)*len(b)),尽管这对于列表来说是最坏情况。 - Patrick Artner

12

虽然使用集合更酷,但您也可以打乱12名球员的列表并对其进行切片:

import random

all_players = list(range(12))

random.shuffle(all_players)

print(all_players[:6])
print(all_players[6:])

输出:

[3, 7, 10, 11, 0, 2]
[4, 8, 5, 6, 9, 1]

特别是如果您需要多次执行此操作,您可以避免反复创建多个集合/列表,而是使用一个包含12个元素的列表作为数据存储器。


时间:

import random

for l in range(12,30,2):

    def shuffle():
      all_players = list(range(l))
      random.shuffle(all_players)
      return all_players[: l // 2], all_players[l // 2 :]
      
    def sets():
      all_players = set(range(l))
      team1 = set(random.sample(all_players, l//2))
      return team1, all_players - team1

    from timeit import timeit

    print(l, timeit(shuffle, number=10000))
    print(l, timeit(sets, number=10000), "\n")

输出:

12 0.27789219999999994   # shuffle marginally faster
12 0.2809480000000001    # sets

14 0.3270378999999999    # still less memory but slower
14 0.3056880999999998    # sets faster

[...]

26 0.6052818999999996
26 0.4748621000000002

28 0.6143755999999998
28 0.49672119999999964

1
你需要将每个情况与12个集合中的玩家进行比较,但列表中的计数会增加。 - Michael Szczesny
@mikk 谢谢,看到了并修复了 :) 只是在编辑 - 不幸的是结果相同。设置规则为14+。 - Patrick Artner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接