2013-02-17 18 views
8

Próbuję zrobić program loterii dla mojej szkoły (mamy system ekonomiczny).Jak wybrać losową linię z pliku tekstowego

Mój program generuje liczby i zapisuje je w pliku tekstowym. Kiedy chcę "wyciągnąć" numery z mojego generatora, chcę, aby był on zwycięzcą.

Pytanie: W jaki sposób mam Python wybrać losową linię z mojego pliku tekstowego i podać mój wynik jako numer?

Odpowiedz

15

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

Zakładając, że plik jest stosunkowo niewielka, co następuje to chyba najprostszy sposób, aby to zrobić:

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

z jakiegoś powodu, gdy próbuję metodę otrzymuję następujący komunikat _italic_ ** pogrubiony ** 'Traceback (najnowsza rozmowę ostatnia): Plik„/ Users/pilotkid/Dokumenty/loterii. py ", linia 338, w line = random.choice (open ('KEEP-IMPORANT.txt'). readlines()) Plik" /System/Library/Frameworks/Python.framework/Versions/2.7/lib/ python2.7/random.py ", wiersz 274, w wyborze return seq [int (self.random() * len (seq))] # podnosi IndexError jeśli seq jest pusty IndexError: indeks listy poza zakresem wylogowanie [Proces zakończony] ' –

+0

Czy plik jest pusty? – NPE

+0

okazuje się, że nie tworzył pliku. Dziwne dzięki za cały twój czas –

2

Off szczycie mojej głowie:

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

inne podejście:

import random, fileinput 

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

Dystrybucja:

$ 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 

nie zobaczyć skewnes ale chyba zestaw danych jest zbyt mały ...

+0

To przekreśla wybór w kierunku liczb, które pojawiają się wcześniej w pliku. – chepner

+0

@chepner - patrz aktualizacja. Nie widzę skewów ... –

+0

Jest trochę inaczej, niż się spodziewałem (nie uważnie czytałem twojego kodu). Zasadniczo wybierasz zestaw liczb od 1 do 10, a następnie wyprowadzasz największy. Więc chociaż istnieje większa szansa, że ​​1 zostanie wybrane jako część zestawu (w rzeczywistości zawsze będzie * częścią zestawu, ponieważ 'randrange (0,1)' zawsze zwróci 0), to nigdy nie zostanie zwrócone chyba że wybrano * nie * inny numer. Zauważ, że twoja dystrybucja wygląda jak odwrócony krzywa dzwonowa, przy czym skrajne liczby są wybierane symbolicznie częściej niż średnie liczby. – chepner

2

z niewielkimi zmianami do pliku wejściowego (zapisać numer pozycji w pierwszej linii), można wybierz numer równomiernie bez konieczności wcześniejszego odczytu całego pliku do pamięci.

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 

Powiedz, że masz 100 numerów. Prawdopodobieństwo wyboru pierwszej liczby to 1/100. Prawdopodobieństwo wyboru drugiej liczby to (99/100) (1/99) = 1/100. Prawdopodobieństwo wybrania trzeciego numeru to (99/100) (98/99) (1/98) = 1/100. Pomijam formalny dowód, ale szanse na wybranie dowolnej ze 100 liczb to 1/100.

Nie jest absolutnie konieczne przechowywanie licznika w pierwszym wierszu, ale oszczędza to kłopotu z koniecznością przeczytania całego pliku tylko po to, aby policzyć wiersze. Tak czy inaczej, nie musisz przechowywać całego pliku w pamięci, aby wybrać jedną linię z takim samym prawdopodobieństwem.

+1

jeśli masz już liczbę linii jako pierwszy element, to jest nie ma potrzeby wywoływania "random.randrange" dla każdej linii. po prostu losowo wybierz numer linii i przejdź do tej linii. – mata

9

Jeśli plik jest bardzo duży - można dążyć do przypadkowej lokalizacji w pliku danego rozmiaru pliku, a następnie dostać następną pełną linię:

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

ta metoda dawałaby krótszym liniom mniejszą szansę na wybranie, więc nie jest dobrym wyborem, jeśli naprawdę chcesz, aby generator losowy wybierał każdą linię z takim samym prawdopodobieństwem. – mata

+0

to również nigdy nie zwróci pierwszej linii i nie zwróci linii w ogóle, gdy random_point jest w ostatnim wierszu. –

-1

Widziałem samouczki Python i znaleźć ten fragment:

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

Chociaż większość z metod podanych tutaj będzie działać, ale mają tendencję do załadowania całego pliku w pamięci na raz. Ale nie takie podejście. Więc nawet jeśli pliki są duże, to działałoby.

Podejście to nie jest intuicyjne na pierwszy rzut oka. Twierdzenie za tym stwierdza, że ​​gdy widzieliśmy N linii istnieje prawdopodobieństwo dokładnie 1/N, że każdy z nich jest wybrany do tej pory.

From Page no 123 of 'Python Cookbook '

Powiązane problemy