Python 哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两
Python 哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两,python,random,line,large-files,readline,Python,Random,Line,Large Files,Readline,哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两次会比N个搜索数(理想情况下)快。也许你可以通过将文件大小除以一行的平均大小(你说你知道)来估计行数,在任何情况下,两次读取文件仍然是O(M).我想我对这条线的长度表达得有点糟糕。我知道一个文件中的行的长度大致相同。但是,文件A和B之间的平均行
哦,谢谢!我将尝试包括这些优化,因为我事先不知道行数。因此,这种方法需要我循环输入文件两次。首先要得到行数。第二步打印所选行。基本上是两次第二次读取所有行,以确定该行是否要输出(在随机数列表中)。我将测试它,因为它不需要很长的时间来写,但我怀疑读取所有行两次会比N个搜索数(理想情况下)快。也许你可以通过将文件大小除以一行的平均大小(你说你知道)来估计行数,在任何情况下,两次读取文件仍然是O(M).我想我对这条线的长度表达得有点糟糕。我知道一个文件中的行的长度大致相同。但是,文件A和B之间的平均行长度可能不同(例如100和50000个字符)。相应地编辑问题。估计行数可能有三个结果。首先,我估计正确,程序按预期运行。其次,估计值太高,这会导致选择一条不存在的线(然后我可以选择一条新的随机线)。第三,估计值太低,最后一行不可能出现在输出中(对此无能为力?)。在任何情况下,我都会尝试这种方法,看看它是如何进行的。因此,您只能阅读第一行并使用它的长度。这并不重要,因为与原始算法中约5000次迭代相比,1次或2次迭代可以忽略不计。你应该试试看它是否运行得更快。类似于zenpoy的建议。我必须查看mmap。读取整个文件需要很多时间。从同一个文件中选择5000行时,单个循环超过60000000行需要比我的算法更多的时间。幸运的是,我可以接受有点偏斜的结果(至少在我当前任务的上下文中)。但如果我需要一个统一的样品,这似乎是一个好办法+我喜欢这个!我有一个类似的问题,我确信我必须读两遍文件。我可能错了,但正如你所描述的,我认为随机选择第一行是不可能的,因为你总是从随机选择的位置向前抓取一大块,并使用下一行。它可以被平衡和微调,以便第一行和最后一行被选中的机会是相同的-这并不难。最好还是将文件放入一个索引的sqlite表中,并使用sql了解文件大小并检索随机行。
inputSize=os.path.getsize(options.input)
usedPositions=[] #Start positions of the lines already in output
with open(options.input) as input:
with open(options.output, 'w') as output:
#Handling of header lines
for i in range(int(options.header)):
output.write(input.readline())
usedPositions.append(input.tell())
# Find and write all random lines, except last
for j in range(int(args[0])):
input.seek(random.randrange(inputSize)) # Seek to random position in file (probably middle of line)
input.readline() # Read the line (probably incomplete). Next input.readline() results in a complete line.
while input.tell() in usedPositions: # Take a new line if current one is taken
input.seek(random.randrange(inputSize))
input.readline()
usedPositions.append(input.tell()) # Add line start position to usedPositions
randomLine=input.readline() # Complete line
if len(randomLine) == 0: # Take first line if end of the file is reached
input.seek(0)
for i in range(int(options.header)): # Exclude headers
input.readline()
randomLine=input.readline()
output.write(randomLine)
import random
N = 5000
with open('file.in') as fin:
line_count = sum(1 for i in fin)
fin.seek(0)
to_take = set(random.sample(xrange(line_count), N))
for lineno, line in enumerate(fin):
if lineno in to_take:
pass # use it
#! /usr/bin/python
# coding: utf-8
import random, os
CHUNK_SIZE = 1000
PATH = "/var/log/cron"
def pick_next_random_line(file, offset):
file.seek(offset)
chunk = file.read(CHUNK_SIZE)
lines = chunk.split(os.linesep)
# Make some provision in case yiou had not read at least one full line here
line_offset = offset + len(os.linesep) + chunk.find(os.linesep)
return line_offset, lines[1]
def get_n_random_lines(path, n=5):
lenght = os.stat(path).st_size
results = []
result_offsets = set()
with open(path) as input:
for x in range(n):
while True:
offset, line = pick_next_random_line(input, random.randint(0, lenght - CHUNK_SIZE))
if not offset in result_offsets:
result_offsets.add(offset)
results.append(line)
break
return results
if __name__ == "__main__":
print get_n_random_lines(PATH)
import random
def random_sample(n, items):
results = []
for i, v in enumerate(items):
r = random.randint(0, i)
if r < n:
if i < n:
results.insert(r, v) # add first n items in random order
else:
results[r] = v # at a decreasing rate, replace random items
if len(results) < n:
raise ValueError("Sample larger than population.")
return results
from itertools import islice
with open(options.input) as input:
with open(options.output, 'w') as output:
# Handling of header lines
# Use islice to avoid buffer issues with .readline()
for line in islice(input, int(options.header)):
output.write(line)
# Pick a random sample
for line in random_sample(int(args[0]), input):
output.write(line)