生成4000个独特的伪随机笛卡尔坐标FASTER?

时间:2010-11-12 23:57:12

标签: python

x和y的范围是0到99。

我目前正在这样做:

excludeFromTrainingSet = []
while len(excludeFromTrainingSet) < 4000:
    tempX = random.randint(0, 99)
    tempY = random.randint(0, 99)
    if [tempX, tempY] not in excludeFromTrainingSet:
        excludeFromTrainingSet.append([tempX, tempY])

但这需要很长时间,我真的需要加快速度。

有什么想法吗?

8 个答案:

答案 0 :(得分:6)

Vincent Savard的answer速度几乎是此处提供的第一个解决方案的两倍。


这是我的看法。它需要元组而不是可靠性列表:

def method2(size):
    ret = set()
    while len(ret) < size:
        ret.add((random.randint(0, 99), random.randint(0, 99)))
    return ret

确保限制是正确的,正如其他回答者所指出的那样。对于合理的输入,这是更好的算法O(n)而不是O(n ^ 2),因为set而不是list。另外,python在加载locals方面要比globals更有效,所以总是把这些东西放在一个函数中。

编辑:实际上,由于概率分量,我不确定它们分别是O(n)和O(n ^ 2)但是如果将n作为它们的唯一元素的数量,则估计是正确的看到。当它们接近可用空间的总数时,它们都会变慢。如果你想要一个接近可用总数的点数,那么最好使用:

import random
import itertools

def method2(size, min_, max_):
    range_ = range(min_, max_)
    points = itertools.product(range_, range_)
    return random.sample(list(points), size)

这将是一个记忆力,但随着点密度的增加肯定会更快,因为它避免了多次查看同一点。另一个值得分析的选项(可能比上一个更好)将是

def method3(size, min_, max_):
    range_ = range(min_, max_)
    points = list(itertools.product(range_, range_))

    N = (max_ - min_)**2
    L =  N - size
    i = 1
    while i <= L:
        del points[random.randint(0, N - i)]
        i += 1
    return points

答案 1 :(得分:4)

我确定有人会使用numpy进入这里,但是如何使用set和tuple? E.g:

excludeFromTrainingSet = set()
while len(excludeFromTrainingSet) < 40000:
    temp = (random.randint(0, 99), random.randint(0, 99))
    if temp not in excludeFromTrainingSet:
        excludeFromTrainingSet.add(temp)

编辑:这不是一个无限循环,因为只有100 ^ 2 = 10000个可能的结果,你等到40000?

答案 2 :(得分:4)

我的建议:

def method2(size):
    randints = range(0, 100)
    excludeFromTrainingSet = set()

    while len(excludeFromTrainingSet) < size:
        excludeFromTrainingSet.add((random.choice(randints), random.choice(randints)))
    return excludeFromTrainingSet

不是每次生成2个随机数,而是首先生成0到99之间的数字列表,然后选择2并附加到列表中。正如其他人指出的那样,只有10 000种可能性,所以你不能循环直到你获得4万,但你明白了。

答案 3 :(得分:4)

列出所有可能的(x,y)值:

allpairs = list((x,y) for x in xrange(99) for y in xrange(99))

# or with Py2.6 or later:
from itertools import product
allpairs = list(product(xrange(99),xrange(99)))

# or even taking DRY to the extreme
allpairs = list(product(*[xrange(99)]*2))

随机播放列表:

from random import shuffle
shuffle(allpairs)

读取第一个'n'值:

n = 4000
trainingset = allpairs[:n]

这在我的笔记本电脑上非常不稳定。

答案 4 :(得分:1)

您可以创建一个随机值的查找表...在该查找表中创建一个随机索引,然后使用静态增量计数器逐步执行...

答案 5 :(得分:1)

生成 4万数字不可避免地需要一段时间。但是您正在对excludeFromTrainingSet执行O(n)线性搜索,这需要花费很长时间,尤其是在此过程的后期。改用一套。您还可以考虑生成许多坐标集,例如过夜并腌制它们,因此您不必为每次测试运行生成新数据(不知道您正在做什么,所以这可能会或可能没有帮助)。正如有人所指出的,使用元组不仅是语义上正确的选择,它还可能有助于提高性能(元组创建比列表创建更快)。编辑:愚蠢我,在使用集合时使用元组必需,因为集成员必须是可散列的,列表是不可删除的。

但是在你的情况下,你的循环没有终止,因为0..99是100个数字,而它们的两个元组只有100 ^ 2 = 10000个唯一组合。修复此问题,然后应用上述内容。

答案 6 :(得分:0)

采取Vince Savard的代码:

>>> from random import choice
>>> def method2(size):
...     randints = range(0, 100)
...     excludeFromTrainingSet = set()
...     while True:
...         x = size - len(excludeFromTrainingSet)
...         if not x:
...             break
...         else:
...             excludeFromTrainingSet.add((choice(randints), choice(randints)) for _ in range(x))
...     return excludeFromTrainingSet
... 
>>> s = method2(4000)
>>> len(s)
4000

这不是一个很好的算法,因为它必须处理冲突,但是元组生成使它可以容忍。这在我的笔记本电脑上运行大约一秒钟。

答案 7 :(得分:0)

## for py 3.0+
## generate 4000 points in 2D
##
import random 
maxn = 10000
goodguys = 0
excluded = [0 for excl in range(0, maxn)]
for ntimes in range(0, maxn):
  alea = random.randint(0, maxn - 1)
  excluded[alea] += 1
  if(excluded[alea] > 1): continue 
  goodguys += 1
  if goodguys > 4000: break
  two_num = divmod(alea, 100)  ## Unfold the 2 numbers
  print(two_num)