Python 如何从文本文件中选择随机行

Python 如何从文本文件中选择随机行,python,file,random,python-3.3,Python,File,Random,Python 3.3,我正试图为我的学校做一个彩票计划,因为我们有一个经济体系 我的程序生成数字并将其保存到文本文件中。当我想从我的生成器中提取数字时,我希望它确保有一个赢家 问:如何让Python从我的文本文件中随机选择一行,并将输出作为该数字 如何让python从文本文件中随机选择一行,并将输出作为该数字 假设文件相对较小,以下可能是最简单的方法: import random line = random.choice(open('data.txt').readlines()) 不经意间: import rand

我正试图为我的学校做一个彩票计划,因为我们有一个经济体系

我的程序生成数字并将其保存到文本文件中。当我想从我的生成器中提取数字时,我希望它确保有一个赢家

问:如何让Python从我的文本文件中随机选择一行,并将输出作为该数字

如何让python从文本文件中随机选择一行,并将输出作为该数字

假设文件相对较小,以下可能是最简单的方法:

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

不经意间:

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

我看不到skewnes,但可能是数据集太小了…

只需对输入文件稍加修改,即可将项目数存储在第一行,您可以统一选择一个数字,而无需先将整个文件读入内存

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/1001/99=1/100。选择第三个数字的概率为99/10098/991/98=1/100。我将跳过正式的证明,但从100个数字中选择任何一个的几率是1/100


严格来说,没有必要将计数存储在第一行中,但这样可以省去只需读取整个文件来计算行数的麻烦。无论哪种方式,您都不需要将整个文件存储在内存中,就可以以相同的概率选择任何一行。

如果文件非常大,您可以根据文件大小查找文件中的任意位置,然后获得下一行:

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

我看了一本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)
虽然这里给出的大多数方法都是可行的,但是它们倾向于一次将整个文件加载到内存中。但不是这种方法。因此,即使文件很大,这也会起作用

乍一看,这种方法不是很直观。这背后的定理表明,当我们在中看到N条线时,到目前为止,每一条线都被选中的概率为1/N


这会使选择偏向文件前面出现的数字。这与我预期的略有不同,因为我没有仔细查看您的代码。您基本上是选择一组从1到10的数字,然后输出最大的一个。因此,尽管1被选为集合的一部分的可能性更大,但事实上,它将始终是集合的一部分,因为randrange0,1将始终返回0,除非没有选择其他数字,否则它将永远不会返回。请注意,您的分布看起来像一条倒钟形曲线,选择极端数的频率明显高于选择中间数的频率。@chepner-您在这里找到了一些东西。今天学到了一些新东西。我想我会在发行版上玩一会儿。Thanx.所以,我算出了一些概率,偏向于选择较小的数字和偏向于输出较大的数字完全抵消了,所以你应该有1/10的机会输出10个数字中的任何一个。例如,选择数字3的几率是1/3,但不选择较大数字的几率是3/44/5…9/10,两者的乘积正好是1/10。我认为我看到的倒钟形曲线可能是由于样本量小。没有歪斜。该算法产生均匀分布@切普纳:这是一个众所周知的故事。这种方法会使较短的行被选择的机会更小,因此如果您真的希望随机生成器以相同的概率选择每一行,那么这不是一个好的选择。它也不会返回第一行,并且在random_point位于最后一行时根本不会返回一行。如果您已经将行数作为第一个元素,这样就不需要为每行调用random.randrange。只需随机选择行号并向前移动到该行即可。
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()