1

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

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

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

我知道如何做到这一点,但我希望列表包含大量数字、100 万个数字或更多。我自己创建了 2 种方法来解决这个问题,它们都有自己的问题,其中slow一个产生了MemoryError.

方法1 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)

方法2 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 更好)我想知道如何创建一个更好地满足我的要求的列表。

4

5 回答 5

2

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

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。我建议您找到一种处理少量样本的方法。

于 2013-11-06T23:34:19.113 回答
1

尝试:

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

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

于 2013-11-06T23:33:53.300 回答
1

由于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

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

于 2013-11-06T23:43:01.257 回答
0

You could use a set instead of a list, and avoid checking for duplicates.

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
于 2013-11-06T23:50:24.580 回答
0

Since your sample size is such a large percentage of the items being sampled, a much faster approach is to shuffle the list of items and then just remove the first or last n items.

import random

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

If samples > end it will just return the whole list

If the list is too large for memory, you can break it into parts and store the parts on disc. In that case a random choice should be made to choose a section, then an item in the section and remove it for each sample required.

于 2013-11-06T23:50:47.517 回答