Как выбрать случайную строку из текстового файла

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

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

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

7 ответов


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

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

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

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

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()

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, что каждый из них выбран до сих пор.

со страницы № 123 " поваренной книги Python'


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

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.

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


С моей макушки:

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]

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

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

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


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

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)