2013-02-17 5 views
8

Я пытаюсь сделать программу лотереи для своей школы (у нас есть экономическая система).Как выбрать случайную строку из текстового файла

Моя программа генерирует числа и сохраняет их в текстовом файле. Когда я хочу «вытащить» цифры из своего генератора, я хочу, чтобы он удостоверился, что есть победитель.

В: Как мне выбрать Python случайную строку из моего текстового файла и дать мой результат как номер?

ответ

15

How do I have python select a random line out of my text file and give my output as that number?

Предполагая, что файл является относительно небольшим, следующий, возможно, самый простой способ сделать это:

import random 
line = random.choice(open('data.txt').readlines()) 
+0

по какой-то причине, когда я пытаюсь свой метод, который я получаю следующее сообщение _italic_ ** жирный ** 'Traceback (самый последний вызов последним): Файл«/ Users/pilotkid/Документы/лотерею. py ", строка 338, в line = random.choice (open ('KEEP-IMPORANT.txt'). readlines()) Файл« /System/Library/Frameworks/Python.framework/Versions/2.7/lib/ python2.7/random.py ", строка 274, по выбору return seq [int (self.random() * len (seq))] # вызывает индексError, если seq пуст IndexError: индекс индекса за пределами допустимого диапазона выход из системы [Процесс завершен] ' –

+0

Неверный файл? – NPE

+0

получается, что он не делал файл. Нечетное спасибо за все ваше время –

2

Off верхней части моей головы:

import random 
def pick_winner(self): 
    lines = [] 
    with open("file.txt", "r") as f: 
     lines = f.readlines(); 
    random_line_num = random.randrange(0, len(lines)) 
    return lines[random_lines_num] 
1

другой подход:

import random, fileinput 

text = None 
for line in fileinput.input('data.txt'): 
    if random.randrange(fileinput.lineno()) == 0: 
     text = line 
print text 

Распределение:

$ seq 1 10 > data.txt 

# run for 100000 times 
$ ./select.py > out.txt 

$ wc -l out.txt 
100000 out.txt 

$ sort out.txt | uniq -c 
    10066 1 
    10004 10 
    10023 2 
    9979 3 
    9926 4 
    9936 5 
    9878 6 
    10023 7 
    10154 8 
    10011 9 

Я не вижу skewnes, но, возможно, набор данных слишком мал ...

+0

Это заставляет задуматься о выборе номеров, которые появляются ранее в файле. – chepner

+0

@chepner - см. Обновление. Не вижу перекосов ... –

+0

Это немного искажено, чем я ожидал (я не смотрел на ваш код осторожно). Вы в основном выбираете набор чисел от 1 до 10, а затем выводите самый большой. Таким образом, хотя есть большая вероятность того, что 1 будет выбрано как часть набора (на самом деле он всегда будет * быть частью множества, так как 'randrange (0,1)' всегда будет возвращать 0), он никогда не будет возвращен если * no * другой номер выбрано. Обратите внимание, что ваше распределение выглядит как перевернутая кривая звонка, причем крайние числа выбираются значительно чаще, чем средние числа. – chepner

2

С небольшими изменениями в входном файле (хранить количество элементов в первой строке), вы можете выберите номер равномерно, не прочитав сначала весь файл в памяти.

import random 
def choose_number(frame): 
    with open(fname, "r") as f: 
     count = int(f.readline().strip()) 
     for line in f: 
      if not random.randrange(0, count): 
       return int(line.strip()) 
      count-=1 

Скажем, у вас есть 100 номеров. Вероятность выбора первого номера - 1/100. Вероятность выбора второго номера равна (99/100) (1/99) = 1/100. Вероятность выбора третьего номера равна (99/100) (98/99) (1/98) = 1/100. Я пропущу формальное доказательство, но вероятность выбора любого из 100 номеров - 1/100.

Нет необходимости хранить счет в первой строке, но это избавляет вас от необходимости читать весь файл только для подсчета строк. В любом случае вам не нужно хранить весь файл в памяти, чтобы выбрать любую одну строку с равной вероятностью.

+1

, если у вас уже есть количество строк в качестве первого элемента, тогда есть не нужно называть 'random.randrange' для каждой строки. просто произвольно выберите номер строки и перейдите к этой строке. – mata

9

Если файл очень большой - вы можете обратиться к случайному местоположению в файле заданного размера файла, а затем получить следующую полную строку:

import os, random 
def get_random_line(file_name): 
    total_bytes = os.stat(file_name).st_size 
    random_point = random.randint(0, total_bytes) 
    file = open(file_name) 
    file.seek(random_point) 
    file.readline() # skip this line to clear the partial line 
    return file.readline() 
+3

этот метод дал бы коротким линиям меньший шанс быть выбранным, поэтому это не лучший выбор, если вы действительно хотите, чтобы ваш случайный генератор выбирал каждую строку с той же вероятностью. – mata

+0

он также никогда не вернет первую строку и не вернет строку вообще, когда random_point находится в последней строке. –

-1

Я видел питона учебники и нашел этот фрагмент кода:

def randomLine(filename): 
#Retrieve a random line from a file, reading through the file once 
     fh = open("KEEP-IMPORANT.txt", "r") 
     lineNum = 0 
     it = '' 

     while 1: 
       aLine = fh.readline() 
       lineNum = lineNum + 1 
       if aLine != "": 
         # 
         # How likely is it that this is the last line of the file ? 
         if random.uniform(0,lineNum)<1: 
           it = aLine 
       else: 
         break 
     nmsg=it 
     return nmsg 
     #this is suposed to be a var pull = randomLine(filename) 
4
def random_line(): 
    line_num = 0 
    selected_line = '' 
    with open(filename) as f: 
     while 1: 
      line = f.readline() 
      if not line: break 
      line_num += 1 
      if random.uniform(0, line_num) < 1: 
       selected_line = line 
    return selected_line.strip() 

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

Этот подход на первый взгляд не очень интуитивно понятен. В этой теореме утверждается, что, когда мы видели N строк, существует вероятность точно 1/N, что каждый из них выбран до сих пор.

From Page no 123 of 'Python Cookbook '