代码之家  ›  专栏  ›  技术社区  ›  Shane

如何在python中从一个文件中随机读取一行?

  •  30
  • Shane  · 技术社区  · 16 年前

    9 回复  |  直到 6 年前
        1
  •  69
  •   Eugene Yarmash    5 年前

    不是内置的,而是算法 R(3.4.2) (Waterman的“水库算法”)摘自Knuth的“计算机编程的艺术”(非常简化的版本):

    import random
    
    def random_line(afile):
        line = next(afile)
        for num, aline in enumerate(afile, 2):
            if random.randrange(num):
                continue
            line = aline
        return line
    

    这个 num, ... in enumerate(..., 2) randrange 因此将为0,概率为 1.0/num --这就是我们必须替换当前所选行的概率(引用算法的样本大小1的特例——参见Knuth的书以获得正确性的证明==当然,我们也是在一个足够小的“库”以适应内存的情况下;-)。。。以及我们 所以。

        2
  •  38
  •   Tony Veijalainen    15 年前
    import random
    lines = open('file.txt').read().splitlines()
    myline =random.choice(lines)
    print(myline)
    

    对于很长的文件: 根据文件的长度在文件中随机放置,并在位置后找到两个换行符(或换行符和文件结尾)。如果原始查找位置是<100(如果我们在最后一行中结束),请在文件开头之前或从文件开头执行100个字符。

    然而,这是过于复杂,因为文件是迭代器。所以呢列一张单子随机选择(如果您需要很多,请使用随机抽样):

    import random
    print(random.choice(list(open('file.txt'))))
    
        3
  •  13
  •   cji    16 年前

    import random
    
    random_lines = random.choice(open("file").readlines())
    

    会成功的。

        4
  •  12
  •   Nick Pandolfi    12 年前

    linereader

    以下是使用此软件包获取随机行的简单解决方案:

    from random import randint
    from linereader import dopen
    
    length = #lines in file
    filename = #directory of file
    
    file = dopen(filename)
    random_line = file.getline(randint(1, length))
    

    第一次这样做是最糟糕的,因为linereader必须以特殊格式编译输出文件。完成后,linereader可以快速访问文件中的任何行,不管文件大小如何。

    如果您的文件非常小(小到可以容纳一个MB),那么您可以替换 dopen copen ,并在内存中生成文件的缓存条目。这不仅更快,而且可以在文件加载到内存时获得文件中的行数;这是为您完成的。你需要做的就是生成随机行号。下面是一些示例代码。

    from random import randint
    from linereader import copen
    
    file = copen(filename)
    lines = file.count('\n')
    random_line = file.getline(randint(1, lines))
    

    我真的很高兴,因为我看到有人可以从我的包裹中受益!很抱歉没有答案,但这个软件包肯定可以应用于许多其他问题。

        5
  •  4
  •   ideasman42    11 年前

    如果不想读取整个文件,可以在文件中间查找,然后向后查找换行符,然后调用 readline

    这是一个Python3脚本,它就是这样做的,

    这种方法的一个缺点是短线出现的可能性较低。

    def read_random_line(f, chunk_size=16):
        import os
        import random
        with open(f, 'rb') as f_handle:
            f_handle.seek(0, os.SEEK_END)
            size = f_handle.tell()
            i = random.randint(0, size)
            while True:
                i -= chunk_size
                if i < 0:
                    chunk_size += i
                    i = 0
                f_handle.seek(i, os.SEEK_SET)
                chunk = f_handle.read(chunk_size)
                i_newline = chunk.rfind(b'\n')
                if i_newline != -1:
                    i += i_newline + 1
                    break
                if i == 0:
                    break
            f_handle.seek(i, os.SEEK_SET)
            return f_handle.readline()
    
        6
  •  4
  •   Eugene Yarmash    7 年前

    Alex Martelli的稍微改进版 answer ,它处理空文件(通过返回 default 值):

    from random import randrange
    
    def random_line(afile, default=None):
        line = default
        for i, aline in enumerate(afile, start=1):
            if randrange(i) == 0:  # random int [0..i)
                line = aline
        return line
    

    这个 approach O(n) 时间和 O(1) 空间。

        7
  •  2
  •   Ignacio Vazquez-Abrams    16 年前

    找一个随机的位置,读一行并丢弃它,然后读另一行。线路分布不正常,但这并不总是重要的。

        8
  •  1
  •   Ivan Vinogradov    7 年前

    如果不想将整个文件加载到RAM中 f.read() f.readlines() ,可以这样得到随机线:

    import os
    import random
    
    
    def get_random_line(filepath: str) -> str:
        file_size = os.path.getsize(filepath)
        with open(filepath, 'rb') as f:
            while True:
                pos = random.randint(0, file_size)
                if not pos:  # the first line is chosen
                    return f.readline().decode()  # return str
                f.seek(pos)  # seek to random position
                f.readline()  # skip possibly incomplete line
                line = f.readline()  # read next (full) line
                if line:
                    return line.decode()  
                # else: line is empty -> EOF -> try another position in next iteration
    
    

    但是,如果您关心分发,则此代码不是您的选项。

        9
  •  0
  •   GoTrained    9 年前

    您可以将这些行添加到set()中,这将随机更改它们的顺序。

    filename=open("lines.txt",'r')
    f=set(filename.readlines())
    filename.close()
    

    要查找第一行:

    print(next(iter(f)))
    

    print(list(f)[2])
    

    要列出集合中的所有行:

    for line in f:
        print(line)
    
        10
  •  0
  •   Philip Hughes    8 年前

    import random
    choicefile=open("yourfile.txt","r")
    linelist=[]
    for line in choicefile:
        linelist.append(line)
    choice=random.choice(linelist)
    print(choice)
    

    它读取文件的每一行,并将其附加到列表中。然后从列表中随机选择一行。 如果你想删除线一旦被选中,只要做

    linelist.remove(choice)
    

    希望这可能有帮助,但至少没有额外的模块和进口(除了随机)和相对轻量级。

        11
  •  0
  •   HCLivess    8 年前
    import random
    
    with open("file.txt", "r") as f:
        lines = f.readlines()
        print (random.choice(lines))