2

抱歉,如果这很简单,但我一直在寻找一段时间,但找不到一个简单、有效的解决方案。

我有一个二维 Python 列表,它只包含 1 和 0。

例如:

a=[[0,1,0],[0,1,1],[1,0,1]]

我希望随机返回 = 1 的随机元素的索引。在这种情况下,我想返回:

[0,1], [1,1], [1,2], [2,0], or [2,2]

以相等的概率。

我可以遍历结构中的每个元素并编译一个合格索引列表,然后使用 random.choice(list) 随机选择一个 - 但这似乎很慢,我不禁觉得有一种更整洁、更 Pythonic 的方式接近这个。我可能会为一个 20x20 的阵列执行此操作,并且需要多次执行此操作,因此我可以尽可能高效地执行此操作。

提前感谢您的任何帮助和建议!

4

5 回答 5

2

我将使用列表推导生成元组列表(位置为 1),然后使用 random.choice :

from random import choice

a = [[0,1,0],[0,1,1],[1,0,1]]
mylist = []

[[mylist.append((i,j)) for j, x in enumerate(v) if x == 1] for i, v in enumerate(a)]
print(choice(mylist))
于 2010-11-22T17:06:50.140 回答
1

我会使用NumPy数组来实现这一点:

from numpy import array
random_index = tuple(random.choice(array(array(a).nonzero()).T))

如果您从一开始就将数据存储在 NumPy 数组中,那么这种方法可能会比使用列表列表执行的任何操作都要快。

如果您想为相同的数据选择多个索引,还有更快的方法。

于 2010-11-22T17:18:02.860 回答
1

random.choice允许我们从列表中随机选择一个元素,因此我们只需要使用列表推导来创建一个元素为 1 的索引列表,然后随机选择一个。

我们可以使用以下列表推导:

>>> a = [[0,1,0],[0,1,1],[1,0,1]]
>>> [(x,y) for x in range(len(a)) for y in range(len(a[x])) if a[x][y] == 1]
[(0, 1), (1, 1), (1, 2), (2, 0), (2, 2)]

这意味着我们可以做到:

>>> import random
>>> random.choice([(x,y) for x in range(len(a)) for y in range(len(a[x])) if a[x][y] == 1])
(1, 1)

如果您将多次执行此操作,则可能值得缓存由推导生成的索引列表,然后从中挑选几次,而不是每次都计算列表推导。

于 2010-11-22T17:36:04.097 回答
0

当您从 random.choice 获得结果时,如果它不再是随机的,请检查它是否是您希望使用正确元素的结果

def return_random(li):
    item = random.choice(li)
    if item == 1: #insert check here
        return item
    else:
        return_random(li)

编辑:为了避免与 re 模块混淆,谢谢

于 2010-11-22T17:03:13.107 回答
0

另一个想法是以完全不同的方式存储数据:使用一组表示为 1 的条目的索引对而不是列表列表。在您的示例中,这将是

s = set((0, 1), (1, 1), (1, 2), (2, 0), (2, 2))

要随机选择索引对,请使用

random.choice(list(s))

要将条目设置为 1,请使用

s.add((i, j))

要将条目设置为 0,请使用

s.remove((i, j))

要翻转条目,请使用

s.symmetric_difference_update([(i, j)])

要检查条目是否为 1,请使用

(i, j) in s
于 2010-11-22T17:36:16.530 回答