我正在尝试为我的学校制作一个彩票计划(我们有一个经济体系)。
我的程序生成数字并将其保存到文本文件中。当我想从我的发电机中“拉”出数字时,我希望它确保有赢家。
问:我如何让 Python 从我的文本文件中随机选择一行并将我的输出作为该数字给出?
我正在尝试为我的学校制作一个彩票计划(我们有一个经济体系)。
我的程序生成数字并将其保存到文本文件中。当我想从我的发电机中“拉”出数字时,我希望它确保有赢家。
问:我如何让 Python 从我的文本文件中随机选择一行并将我的输出作为该数字给出?
如何让 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。
来自“Python Cookbook ”的第 123 页
在我的头顶上:
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
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, 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)