python:从二维网格进行采样而不进行替换

python:从二维网格进行采样而不进行替换,python,algorithm,random,python-3.x,Python,Algorithm,Random,Python 3.x,我需要一个样本,不需要替换,从范围(n)中的所有可能的数字元组中。也就是说,我有一个(0,0),(0,1),(0,n),(1,0),(1,1),(1,n),(n,0),(n,1),(n,n)的集合,我试图得到这些元素的k的样本。我希望避免明确构建此集合 我知道random.sample(range(n),k)是一个简单而有效的方法,如果我需要一个数字序列的样本,而不是一个数字元组的样本 当然,我可以显式地构建包含所有可能(n*n=n^2)元组的列表,然后调用random.sample。但如果k比

我需要一个样本,不需要替换,从
范围(n)
中的所有可能的数字元组中。也就是说,我有一个(0,0),(0,1),(0,n),(1,0),(1,1),(1,n),(n,0),(n,1),(n,n)的集合,我试图得到这些元素的k的样本。我希望避免明确构建此集合

我知道
random.sample(range(n),k)
是一个简单而有效的方法,如果我需要一个数字序列的样本,而不是一个数字元组的样本

当然,我可以显式地构建包含所有可能(
n*n=n^2
)元组的列表,然后调用
random.sample
。但如果
k
n^2
小得多,这可能是无效的


我不确定Python2和Python3的效率是否相同;我使用Python3。

根据您选择的对象的数量,最简单的方法可能是跟踪您已经拾取的对象(通过
),然后重新拾取,直到获得尚未拾取的对象

另一个选择是使用一些简单的数学:

numbers_in_nxn = random.sample(range(n*n), k) # Use xrange in Python 2.x
tuples_in_nxn = [divmod(x,n) for x in numbers_in_nxn]
不用尝试(手头没有python):

见评论。睡眠不足…

你说:

当然,我可以显式地构建 包含所有可能(n*n)的列表= n^2)元组,然后调用 随机抽样。但这可能是真的 如果k小得多,则效率不高 比n^2

那么,在随机选取一个元组之后再构建元组怎么样?也就是说,如果可以在随机选择要拾取的元组之前构建元组,那么可以先拾取元组,然后再构建元组

我不明白你的元组应该是什么样子,但这里有一个例子,虽然我意识到你的元组都是相同长度的,但这表明了原则:

而不是这样做:

>>> import random
>>> all_sequences = [range(x) for x in range(10)]
>>> all_sequences
[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
>>> random.sample(all_sequences, 3)
[[0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6, 7, 8]]
您可以这样做:

>>> import random
>>> selection = random.sample(range(10), 3)
>>> [range(x) for a in selection]
[[0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

这不会给出
n
x
n
中的元组,因为它永远不会给出,比如说
(1,1)
。但是“不替换”意味着什么呢?啊,现在我明白了。k长度为n的不同元组。我想你的意思是
random.sample(range(n*n),k)
,因为当我意识到你把这个部分放进去时,我正在写这篇文章。+1第二个选项对我来说似乎很完美(将
n*n
替换为
range(n*n)
,将
100
替换为
n
)。考虑到
sample
被认为是高效的,我想不出什么时候从集合中绘图会更好。你可以用
divmod(x,n)
+1来代替
(x%n,x//n)
,以获得聪明的答案(并且显然理解OP想要什么)。如果将
range
更改为
xrange
@Kabie,
divmod(x,n)
将返回
(x//n,x%n)
而不是
(x%n,x//n)
,因此它并不完全相同,尽管我认为这在这里并不重要(因此也认为@J.F.Sebastian的评论无关紧要)元组是序列,所以你的句子“需要一个数字序列的样本,而不是一个数字元组。”毫无意义。你是说你需要一个元组序列的样本?在这种情况下,不清楚这些元组的外观。您的代码(
random.sample(范围(n),k)
适用于所有序列、元组、列表、字符串和
集合的任何子类。序列
。您尝试过代码了吗?问题是什么?@Regebro:“元组样本”=“n个元组序列中的k个元组样本”。“序列样本”=“n个元素序列中的k个元素样本”@S.Lott:我的意思是,我不能将序列((0,0)、(0,1)、(0,2)、(1,0)、(1,1)、(1,2)、(2,0)、(2,1)、(2,1)、(2,2))作为一个简单的
范围,我可以简单地应用
示例
>>> import random
>>> selection = random.sample(range(10), 3)
>>> [range(x) for a in selection]
[[0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8], [0, 1, 2, 3, 4, 5, 6, 7, 8]]