【问题标题】:Choose random element in list influenced by its position选择列表中受其位置影响的随机元素
【发布时间】:2014-06-17 04:57:06
【问题描述】:

我有一个包含四个元素的列表,并从中选择一个以最大化我这样做的第一个元素的机会:

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 会很大并且会减慢我的算法。

【问题讨论】:

标签: python python-3.x random


【解决方案1】:

实际上有一个内置函数可以为您执行此操作:

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

【讨论】:

  • 您的两个解决方案都有效,尽管在第一个解决方案中,使用 random.triangular() 可能会导致列表索引中的一个元素,因为它考虑 x 轴上三角形的两端,我不得不添加如果发生这种情况,则函数再次运行的条件。第一个解决方案也非常接近原始行为,但并不完美。第二个就完美了!
【解决方案2】:

@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

【讨论】:

    猜你喜欢
    • 2021-12-30
    • 2012-03-12
    • 2013-10-19
    • 1970-01-01
    • 2014-02-07
    • 1970-01-01
    • 2018-03-25
    • 2011-04-26
    • 2023-02-02
    相关资源
    最近更新 更多