2017-04-27 72 views
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

':

lists[random.randint(0, len(lists) - 1)] 

这从随机选择的列表中随机选择一个项random.choice(old_people + young_people + mid_age)'? – Psidom

+0

如果列表很小(@Psidom) –

+0

'random.choice([random.choice(x)for x in(old_people,young_people,mid_age)])' – SmartManoj

回答

5

假设通过“所有三个列表中的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}) 
+0

在代码片段中我看到的是什么“In”和“out”? – user1712447

2

如果你不想承担连接多个列表的开销(在这种情况下,我不会责怪你 - 这是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) 

这计算的指数,然后遍历列表清单,直到它找到它落在一个,然后返回相应的元素。

0

如果相同的概率需要所有合并名称之间:

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) 
0

您可以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]) 
1

另一种可能的实现。假设输入结构良好。

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