【问题标题】:Create a long list of random values, no duplicates创建一长串随机值,不重复
【发布时间】:2013-11-06 23:30:20
【问题描述】:

我想创建一个给定两个输入的列表,并且在不能有任何重复的条件下。该列表应包含随机的数字序列。那么列表中的数字就是正整数。

  • 输入1:列表长度(var samples

  • 输入2:列表的最大数(var end

我知道如何执行此操作,但我希望列表包含大量数字、100 万个或更多数字。 我自己创建了两种方法来解决这个问题,它们都有自己的问题,其中一个是slow,另一个产生一个MemoryError

方法一,MemoryError

import random

def create_lst_rand_int(end, samples):
    if samples > end:
        print('You cannot create this list')
    else:
        lst = []
        lst_possible_values = range(0, end)
        for item in range(0, samples):
            random_choice = random.choice(lst_possible_values)
            lst_possible_values.remove(random_choice)
            lst.append(random_choice)
        return lst

print create_lst_rand_int(1000000000000, 100000000001)

方法二,slow

import random

def lst_rand_int(end, samples):
    lst = []
    # lst cannot exist under these conditions
    if samples > end:
        print('List must be longer or equal to the highest value')
    else:
        while len(lst) < samples:
            random_int = random.randint(0, end)
            if not random_int in lst:
                lst.append(random_int)
        return lst

print lst_rand_int(1000000000000, 100000000001)

由于我的两种方法都不能很好地工作(方法 1 确实比方法 2 更好),我想知道如何创建一个更好地满足我的要求的列表。

【问题讨论】:

  • 列表需要在内存中吗?
  • 我只需要一个存储在某个地方的列表,以便以后可以轻松访问它。我非常希望它不在外部文件中。
  • 查看所有这些零:如果我没有搞砸我的计算,那么这个列表至少有 3725 GB。你有这么多记忆吗?
  • 我有 4gb 内存,200gb 硬盘。
  • 在我的系统上,Python 整数是 24 字节(由sys.getsizeof 报告)。该帖子要求 100000000001 个整数,这需要 2400000000024 个字节。那是 2235.17 GB(使用 Google 进行方便的转换),或大约 2 TB。这永远不会接近在列出的机器上工作。

标签: python algorithm python-2.7 random int


【解决方案1】:

尝试文档中给出的解决方案:

http://docs.python.org/2/library/random.html#random.sample

要从整数范围中选择样本,请使用 xrange() 对象作为参数。这对于从大量人口中采样特别快速且节省空间:sample(xrange(10000000), 60)。

或者,在你的情况下,random.sample(xrange(0,1000000000000), 100000000001)

这仍然是一个巨大的数据结构,可能适合也可能不适合您的记忆。在我的系统上:

>>> sys.getsizeof(1)
24

因此 100000000001 个样本将需要 2400000000024 字节,或大约 2 TB。我建议您找到一种处理少量样本的方法。

【讨论】:

  • +1 但是你没有说出xrangerange 快的原因:因为range 预先在内存中分配了整个列表,而xrange 返回了一个生成器,从而利用了惰性分配
【解决方案2】:

试试:

temp = xrange(end+1)
random.sample(temp, samples)

random.sample() 不会选择任何重复项。

【讨论】:

  • 当我运行这个脚本而不是退出并抛出内存错误时,它会冻结我的系统。
【解决方案3】:

由于sample 总是返回一个列表,所以你不走运这么大的大小。尝试使用生成器:

def rrange(min, max):
    seen = set()
    while len(seen) <= max - min:
        n = random.randint(min, max)
        if n not in seen:
            seen.add(n)
            yield n

这仍然需要内存来存储看到的元素,但至少不是一次存储所有内容。

【讨论】:

  • 我正在考虑这种方法 - 它肯定会击败 OP 的第二种方法 - 但它最终仍会构建一个同样大的数据结构。只是一个集合而不是一个列表。
  • @PeterDeGlopper:关键是结构是逐步构建的,所以你可以在内存耗尽时采取措施,比如交换部分内存等。
  • 我在运行它时遇到问题,我得到的是这个而不是 lst。 。该函数还应该接受输入、列表中的数字数量、列表中的最高数字
  • @JebediahKerman:这是一个生成器对象。你应该使用for 循环:for n in rrange(...)
  • 很高兴有一个完整的答案,我对python相当陌生
【解决方案4】:

您可以使用集合而不是列表,并避免检查重复项。

def lr2(end, samples):
    lst = set()
    # lst cannot exist under these conditions
    if samples > end:
        print('List must be longer or equal to the highest value')
    else:
        for _ in range(samples):
            random_int = random.randint(0, end)
            lst.add(random_int)
        return lst

【讨论】:

    【解决方案5】:

    由于您的样本量占被抽样项目的很大比例,因此更快的方法是打乱项目列表,然后只删除第一个或最后 n 个项目。

    import random
    
    def lst_rand_int(end, samples):
        lst = range(0, end)
        random.shuffle(lst)
        return lst[0:samples]
    

    如果samples &gt; end 它只会返回整个列表

    如果列表太大而无法存储,您可以将其分成几部分并将部分存储在磁盘上。在这种情况下,应随机选择一个部分,然后选择该部分中的一个项目,并为每个所需的样本删除它。

    【讨论】:

      猜你喜欢
      • 2013-10-28
      • 2011-04-03
      • 1970-01-01
      • 1970-01-01
      • 2012-01-08
      • 1970-01-01
      • 2012-07-20
      • 2023-03-06
      • 1970-01-01
      相关资源
      最近更新 更多