1

2 つの入力が与えられ、重複が存在しないという条件でリストを作成したいと考えています。リストには、ランダムな一連の数字が含まれている必要があります。リスト内の数値は正の整数です。

  • 入力 1: リストの長さ (var samples)

  • 入力 2: リストの最大数 (var end)

これを行う方法はわかっていますが、リストに膨大な数、100 万個、またはそれ以上の数を含めたいと考えています。私はこの問題を自分で解決する 2 つの方法を作成しました。どちらにも問題があり、そのうちslowの 1 つは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() オブジェクトを引数として使用します。これは、サンプル (xrange(10000000), 60) という大きな母集団からサンプリングする場合に特に高速でスペース効率が良いです。

または、あなたの場合、random.sample(xrange(0,1000000000000), 100000000001)

これは依然として巨大なデータ構造であり、記憶に収まるかどうかはわかりません。私のシステムでは:

>>> sys.getsizeof(1)
24

したがって、100000000001 サンプルには 2400000000024 バイト、つまり約 2 テラバイトが必要です。少数のサンプルで作業する方法を見つけることをお勧めします。

于 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

リストの代わりにセットを使用して、重複のチェックを避けることができます。

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

サンプルサイズは、サンプリングされるアイテムの非常に大きな割合であるため、アイテムのリストをシャッフルしてから、最初または最後の n 個のアイテムを削除する方がはるかに高速なアプローチです。

import random

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

samples > endリスト全体を返すだけの場合

リストがメモリに対して大きすぎる場合は、リストを分割してディスクに保存できます。その場合、ランダムにセクションを選択し、次にセクション内の項目を選択し、必要なサンプルごとにそれを削除する必要があります。

于 2013-11-06T23:50:47.517 に答える