假设我有3所列出以相同的概率选择从多个列表中随机值
old_people = ['George', 'Bob', 'Owen']
young_people = ['Sarah', 'Gwen', 'Brittney']
mid_age = ['Larry', 'Missy', 'Greg']
import random
random.choice(old_people)
,从一个挑选,我将如何挑选1名从所有三个列表以相同的概率?
假设我有3所列出以相同的概率选择从多个列表中随机值
old_people = ['George', 'Bob', 'Owen']
young_people = ['Sarah', 'Gwen', 'Brittney']
mid_age = ['Larry', 'Missy', 'Greg']
import random
random.choice(old_people)
,从一个挑选,我将如何挑选1名从所有三个列表以相同的概率?
假设通过“所有三个列表中的1个名字具有相同的概率”意味着每个名字将具有相同的被选择概率,因为在Python 3.6中引入了random.choices
,可以相对直接地完成此操作,而无需连接以构建一个巨型列表。例如:
In [52]: seqs = [old_people, young_people, mid_age]
In [53]: random.choice(random.choices(seqs, weights=map(len, seqs))[0])
Out[53]: 'Larry'
在这里我们选择使用长度加权我们的选择列表中的一个,然后我们从该列表中选择均匀。 seqs
只是列出对子列表的引用,因此不会执行连接。
随着均匀的完整性检查:
In [65]: seqs = [["Bob"], ["Fred", "Sally"]]
In [66]: Counter(random.choice(random.choices(seqs, weights=map(len, seqs))[0])
for _ in range(10**6))
Out[66]: Counter({'Bob': 333484, 'Fred': 332755, 'Sally': 333761})
在代码片段中我看到的是什么“In”和“out”? – user1712447
如果你不想承担连接多个列表的开销(在这种情况下,我不会责怪你 - 这是O(n)应该是O(1)操作),你可以通过选择与连接列表中的位置相对应的索引来做同样的事情,然后索引适当的列表。在代码:
import random
def choose(*lists):
total_len = sum(map(len, lists))
index = random.randint(0, total_len - 1)
for l in lists:
if index < len(l):
return l[index]
else:
index = index - len(l)
这计算的指数,然后遍历列表清单,直到它找到它落在一个,然后返回相应的元素。
如果相同的概率需要所有合并名称之间:
random.choice(old_people + young_people + mid_age)
事情要注意这里的是,如果一个列表中有多个字符串,即“名单”有被选中的概率更高。
如果概率需要是这样的:3所列出应该被拾起的概率相等,并且列表中,每串有相同的概率,然后将其更改为类似:
pick1 = random.choice(old_people)
pick2 = random.choice(young_people)
pick3 = random.choice(mid_age)
foo = [pick1 ,pick2,pick3]
random.choice(foo)
您可以Psidom的建议去(除非该名单是非常大的或者这是一个紧密的循环)或沙善的一个 - 这取决于你的“的定义相等的概率“:
random.choice(old_people + young_people + mid_age)
#or
random.choice([random.choice(_) for _ in
(old_people + young_people + mid_age)])
第一个将创建一个新的列表串接3所列出,它作为参数传递到random.choice
并丢弃它,而第二个将选择一个随机元素形成每个列表,然后再挑选一个的选择(如果你的定义“等概率”适合这个你可以在这里停下来。
如果名单虽小,但您呼叫random.choice
一个循环中,将重复一百万次,你最好级联列表存储在一个变量:
choices = old_people + young_people + mid_age
while True:
choice = random.choice(choices)
do_something_with(choice)
如果列表是非常大的,你可能要避免新的大的大的大名单的创作在内存使用像这样(未经):
def choice(*lists):
lens = [len(_) for _ in lists]
choice = random.randint(0, sum(lens) - 1)
i = 0
for j, size in enumerate(lens):
i += size
if choice < i:
if j:
return lists[j][choice - i]
return lists[j][choice]
choice(old_people, young_people, mid_age)
[编辑]
如果您在再幸运使用Python 3.6或更高版本是,你的建议由DSM:
choices = old_people, young_people, mid_age
choice = random.choice(random.choices(
choices,
weights=[len(_) for _ in choices]
)[0])
另一种可能的实现。假设输入结构良好。
import random
def choose(*lists):
return lists[random.randint(0, len(lists) - 1)] \
[random.randint(0, len(lists[0]) - 1)]
说明
这从列表的列表中随机选择的列表:
[random.randint(0, len(lists[0]) - 1)]
':
这从随机选择的列表中随机选择一个项random.choice(old_people + young_people + mid_age)'? – Psidom
如果列表很小(@Psidom) –
'random.choice([random.choice(x)for x in(old_people,young_people,mid_age)])' – SmartManoj