2012-03-18 5 views
42

Я пробовал использовать random.randint(0, 100), но некоторые номера были одинаковыми. Есть ли метод/модуль для создания уникальных случайных чисел списка?Как создать список уникальных случайных чисел?

def getScores(): 
    # open files to read and write 
    f1 = open("page.txt", "r"); 
    p1 = open("pgRes.txt", "a"); 

    gScores = []; 
    bScores = []; 
    yScores = []; 

    # run 50 tests of 40 random queries to implement "bootstrapping" method 
    for i in range(50): 
     # get 40 random queries from the 50 
     lines = random.sample(f1.readlines(), 40); 
+7

Если они уникальны, то они действительно не случайны. –

+1

@ IgnacioVazquez-Abrams im пытается реализовать метод, который мой профессор назвал «начальной загрузкой», мы делаем некоторые «исследования» в поисковых системах. – iCodeLikeImDrunk

+0

@ IgnacioVazquez-Abrams это они, если они представляют случайные выборки без замены. Это вопрос об общем использовании языка программирования ... мы * используем его для вещей –

ответ

78

Это вернет список из 10 номеров, выбранных из диапазона от 0 до 99, без дубликатов.

random.sample(range(100), 10) 

Со ссылкой на ваш конкретный пример кода, вы, вероятно, хотите, чтобы прочитать все строки из файла раз, а затем выбрать случайные строки из списка сохраненных в памяти. Например:

all_lines = f1.readlines() 
for i in range(50): 
    lines = random.sample(all_lines, 40) 

Таким образом, вам необходимо всего лишь на самом деле прочитать файл один раз, перед вашим циклом. Гораздо эффективнее сделать это, чем вернуться к началу файла и снова вызвать f1.readlines() для каждой итерации цикла.

+0

Я также пробовал это, lines = random.sample (f1.readlines(), 40); он продолжает давать мне «образец больше, чем население», когда я пытался запустить его через цикл ... любые советы? – iCodeLikeImDrunk

+1

Ваш источник содержит менее 40 строк, поэтому 'random.sample()' не может предоставить вам список из 40 строк без дубликатов. –

+0

Вызов списка не нужен, я думаю (для обоих и для 2 и 3). – DSM

3

Если список N чисел от 1 до N генерируется случайным образом, то да, есть вероятность, что некоторые числа могут быть повторены.

Если вам нужен список чисел от 1 до N в случайном порядке, заполните массив с помощью отложенных от 1 до N, а затем используйте Fisher-Yates shuffle.

Update: в @Greg указывает: так как это Python, используйте random.shuffle()

7

Почему бы не создать список 1..100 и перемешайте его с Fisher-Yates алгоритмом?

+15

или, так как это Python, 'random.shuffle()' ... –

+3

иногда быть первым просто недостаточно ... :) –

1

Если вы хотите, чтобы убедиться, что число добавляемых уникальны, вы могли бы использовать Set object

при использовании 2.7 или выше, или импортировать Множества модуль, если нет.

Как уже упоминалось, это означает, что цифры не являются случайными.

6

Greg Hewgill работы (+1), но может быть проблематично с памятью, если размер выборки мал, но население огромно (например, random.sample(insanelyLargeNumber, 10)).

Чтобы исправить это, я бы с этим:

answer = set() 
sampleSize = 10 
answerSize = 0 

while answerSize < sampleSize: 
    r = random.randint(0,100) 
    if r not in answer: 
     answerSize += 1 
     answer.add(r) 
# answer now contains 10 unique, random integers from 0.. 100 
4

Вы можете использовать перетасовать функцию от random модуля, как это:

import random 

my_list = list(xrange(1,100)) # list of integers from 1 to 99 
           # adjust this boundaries to fit your needs 
random.shuffle(my_list) 
print my_list # <- List of unique random numbers 

Отметим здесь, что метод перетасовка Безразлично 't возвращать любой список, как можно было бы ожидать, он только перетасовывает список, переданный по ссылке.

0

С CLI в Win XP:

python -c "import random; print(sorted(set([random.randint(6,49) for i in range(7)]))[:6])" 

В Канаде мы имеем 6/49 лото. Я просто обертываю вышеуказанный код в lotto.bat и запускаю C:\home\lotto.bat или просто C:\home\lotto.

Поскольку random.randint часто повторяет ряд, я использую set с range(7), а затем сократить его до длины 6.

Время от времени, если число повторов более чем в 2 раза в результате длина списка будет меньше, чем 6.

EDIT: Однако random.sample(range(6,49),6) - правильный путь.

0

import random result=[] for i in range(1,50): rng=random.randint(1,20) result.append(rng)

2

Если вам нужно попробовать очень большое количество, вы не можете использовать range

random.sample(range(10000000000000000000000000000000), 10) 

, потому что он бросает:

OverflowError: Python int too large to convert to C ssize_t 

Кроме того, если random.sample не может производить количество деталей вы хотите из-за слишком малого диапазона

random.sample(range(2), 1000) 

он бросает:

ValueError: Sample larger than population 

Эта функция решает обе проблемы:

import random 

def random_sample(count, start, stop, step=1): 
    def gen_random(): 
     while True: 
      yield random.randrange(start, stop, step) 

    def gen_n_unique(source, n): 
     seen = set() 
     seenadd = seen.add 
     for i in (i for i in source() if i not in seen and not seenadd(i)): 
      yield i 
      if len(seen) == n: 
       break 

    return [i for i in gen_n_unique(gen_random, 
            min(count, int(abs(stop - start)/abs(step))))] 

Использование с очень большими числами:

print('\n'.join(map(str, random_sample(10, 2, 10000000000000000000000000000000)))) 

результат Пример:

7822019936001013053229712669368 
6289033704329783896566642145909 
2473484300603494430244265004275 
5842266362922067540967510912174 
6775107889200427514968714189847 
9674137095837778645652621150351 
9969632214348349234653730196586 
1397846105816635294077965449171 
3911263633583030536971422042360 
9864578596169364050929858013943 

Usage, где диапазон меньше, чем количество запрошенных элементов: результат

print(', '.join(map(str, random_sample(100000, 0, 3)))) 

Пример:

2, 0, 1 

Он также работает с отрицательными диапазонами и шаги:

print(', '.join(map(str, random_sample(10, 10, -10, -2)))) 
print(', '.join(map(str, random_sample(10, 5, -5, -2)))) 

Sample результаты:

2, -8, 6, -2, -4, 0, 4, 10, -6, 8 
-3, 1, 5, -1, 3 
1

Вы можете использовать Numpy библиотеки для быстрого ответа, как показано ниже -

Данного кода список сниппает вниз 6 уникальных чисел в диапазоне между 0 до 5. Вы можете настроить параметры для вашего удобства.

import numpy as np 
import random 
a = np.linspace(0, 5, 6) 
random.shuffle(a) 
print(a) 

Выход

[ 2. 1. 5. 3. 4. 0.] 

Он не ставит каких-либо ограничений, как мы видим в random.sample, как указано here.

Надеюсь, это поможет.

Смежные вопросы