我有一个包含四个元素的列表,并选择其中一个最大化我执行此操作的第一个元素的机会:
from random import choice
_list = [19,14,29,3]
element = choice((a[0],a[0],a[0],a[0],a[1],a[1],a[1],a[2],a[2],a[3]))
虽然现在_list
中的元素数量是可变的,但在编写此片段之前尝试保留相同的行为:
from random import choice
_list = [19,14,29,3,.......] # n elements
weighted = []
for i in range(len(_list)):
for j in range(len(_list)-i):
weighted.append(_list[i])
element = choice(weighted)
是否有其他方法可以用更少的代码实现相同的结果并且效率更高?因为我认为如果n
变得太大,那么weighted
将是巨大的并且会减慢我的算法。
答案 0 :(得分:2)
实际上有一个内置函数可以帮到你:
random.triangular(0, length, 0)
Here's the documentation for that function
如果您想自己编写,实际上可以在不使用任何循环的情况下执行此操作。如果你正确看待它,很容易看出来。例如,对于6个元素,您可以将其可视化为:
|
| |
| | |
| | | |
| | | | |
| | | | | |
0 1 2 3 4 5
如果我们将它翻转并将其重新组合在一起,我们就可以得到一个矩形:
5 4 3 2 1 0
| | | | | |
- | | | | |
| - | | | |
| | - | | |
| | | - | |
| | | | - |
| | | | | -
| | | | | |
0 1 2 3 4 5
对于长度为6的列表,矩形的高度为7,宽度为6.因此,您只需要选择两个随机整数并找出该坐标所属的数字。这可以通过简单的计算完成 - 断裂正下方的所有坐标都有x + y等于n-1,而断裂正上方的所有坐标都有x + y等于n。不用多说,这里是代码:
def triangle_random(count):
x = random.randint(0, count-1) # randint includes both ends, so we need count-1
y = random.randint(0, count)
if x + y < count:
return x
else:
return count-1 - x
答案 1 :(得分:0)
@RobWatts通过使用几何体给出了一个很好的答案,但我也找到了另一种有效获得相同结果的方法:
import random
_list = [1,2,3,4]
S = (len(_list)+1)*len(_list)/2 # This represents the Sum of what would be the 'weighted' list composed by elements following a(0) = 1 and a(n) = a(n-1)+1 conditions
x = random.randint(1,S) # pick one element from what would be 'weighted' list
last = 0
for i in range(len(_list)): # get which element in _list 'x' points out
if( x <= len(_list)-i+last ): # first 'len(_list)' elements point out to _list[0], then the next len(_list)-1 elements to _list[1] and so on
element1 = _list[i]
break
else: last += len(_list)-i