从列表中返回随机子子列表及其索引

时间:2014-01-20 14:13:07

标签: python list random

我有一个列表,其中包含以下安排:每个子列表中有N个子列表和N_i个子子列表,其中N_i不一定在整个子列表中相等。每个子子列表包含两个元素(对于所有子子列表都是如此)。这就是这样一个列表的简短版本,有3个子列表和4个,3个,5个和1个子子列表:

a = [[[0.3, 1.2], [0.3, 2.3], [0.3, 4.6], [0.3, 3.4]], [[0.6, 4.5], [0.6, 2.5], [0.6, 7.8]], [[0.2, 1.4], [0.2, 6.3], [0.2, 5.2], [0.2, 2.1], [0.2, 3.6]], [[0.4, 1.3]]]

我需要一种方法从所有可用的子列表中选择一个随机的子子列表,并存储指向它的索引。

我可以使用random.choice并执行:

import random.choice as r_c
s_s_list = r_c(r_c(a))
print s_s_list
[0.6, 7.8]

这有效地返回了所有可用的随机子列表,但它有以下问题:

a-它没有给我指向它的i,j索引(在这种情况下:[1, 2])并且我不能直接使用a.index(s_s_list)因为它是< em>子子列表和

b-因为我需要重复此过程M次来获取M随机不同子子列表(以及指向它们的索引)不行。

c-正如评论中指出的那样,这使得被选择到具有更少元素的子列表内的子子列表的概率更高,并且我需要以相同的概率选择每个子子列表

2 个答案:

答案 0 :(得分:2)

只需使用random.randint()

i = random.randint(0, len(a) - 1)
j = random.randint(0, len(a[i]) - 1)

例如:

>>> a = [[[0.3, 1.2], [0.3, 2.3], [0.3, 4.6], [0.3, 3.4]], [[0.6, 4.5], [0.6, 2.5], [0.6, 7.8]], [[0.2, 1.4], [0.2, 6.3], [0.2, 5.2], [0.2, 2.1], [0.2, 3.6]], [[0.4, 1.3]]]
>>> 
>>> import random
>>> i = random.randint(0, len(a) - 1)
>>> j = random.randint(0, len(a[i]) - 1)
>>> 
>>> a[i][j]  # <-- this is the actual random element
[0.2, 2.1]

重要提示:上面的代码类似于您选择随机元素的代码。 然而,并非所有子子列表都有相同的机会通过此方法获取。例如,考虑:

[[l1, l2, l3, l4, l5, ...], [l0]]

在这种情况下,第一个子列表中的每个子子列表被选中的可能性很小,因为我们必须首先选择i的第一个子列表然后然后选择它为j的正确的子子列表。相比之下,l0有50%的机会被挑选,因为我们必须做的就是选择i的第二个子列表,此时唯一的选择是选择l0 j


您的问题编辑会稍微改变一些事情,因为您确实需要选择M 唯一的子子列表。现在,您可以使用random.sample()尝试此操作:

>>> from random import sample
>>> 
>>> M = 4
>>> 
>>> random.sample([(i,j) for i in range(len(a)) for j in range(len(a[i]))], M)
[(1, 1), (2, 3), (2, 4), (1, 0)]

在Python 2.x中,使用xrange()代替range()

请注意,使用此方法,每个子子列表 都有相同的机会被选中。

我们在这里做的主要是用

创建一个“索引列表”
[(i,j) for i in range(len(a)) for j in range(len(a[i]))]

包含平面列表中每个子子列表的索引:

>>> [(i,j) for i in range(len(a)) for j in range(len(a[i]))]
[(0, 0), (0, 1), (0, 2), (0, 3), (1, 0), (1, 1), (1, 2), (2, 0), (2, 1), (2, 2), (2, 3), (2, 4), (3, 0)]

然后我们从此列表中进行采样,获得所需的结果。

答案 1 :(得分:2)

要跟踪索引,您可以(a)随机选择索引,并使用它们来检索子子列表;或(b)使用enumerate将指数纳入您的清单。

由于您希望在没有替换的情况下进行抽样(即M 不同子子列表),请使用random.sample代替M调用{{1} }}。要在具有相同概率的子列表中进行选择,您必须首先“展平”列表。在添加索引的同时很容易做到这一点。

以下是使用random.choice

的方法
enumerate