让我更好地解释我的问题!我有一个这种格式的输入文件
word1 word2
word3 word4 word5
word4 word6
给定word3,我希望能够获得整行并获得word4和word5。
打开文件,可以解析每一行,但是我的文件很大,需要很长时间。有没有一种经济高效的方法可以做到这一点?
任何帮助表示赞赏!
除非数据以某种可预测的方式排序(例如排序),否则您必须阅读每一行以找到相关的。
with open('/path/file.txt') as input:
for line in input:
words = line.split()
if words and words[0] == 'trigger':
print words[1:]
break # delete this line if you may have multiple matches
上面不会一次将整个文件读入内存(如果它很大) - 它会“一个接一个地”处理这些行(它们将被读取到缓冲区大小的块中)。
一种可能的改进是,如果所有行的大小相同且很长。然后你可以阅读每一行的开头。但是它们必须很长才能有用。
如果您使用的是 unix,那么您可能会发现grep
在子进程中执行命令更快。但这仍然会扫描整个文件(尽管速度更快,在优化的 c 代码中)。
Python 的linecache模块是我所知道的从文件中查找给定行号的最快方法。您想要一行匹配该行中的第一个单词,但也许我们可以使用 linecache 到达那里。所以让我们创建一个从单词到行号的映射:
from linecache import getline, getlines
from collections import defaultdict
first_words = defaultdict(int)
first_words.update(
(line.split()[0], number)
for number, line in enumerate(getlines(filename), 1)
if line
)
从这里,要获得一条线,只需执行以下操作:
>>> getline(filename, first_words['word3'])
'word3 word4 word5\n'
>>> getline(filename, first_words['word4'])
'word4 word6\n'
如果你试图得到一个不是一行中第一个单词的单词,你只会得到空字符串。
>>> getline(filename, first_words['word6'])
''
现在,我想你可能会在几行开头使用相同的单词,在这种情况下,你可能希望得到不止一行。所以这里有一个修改版本来解释这种情况:
from linecache import getline, getlines
from collections import defaultdict
from operator import itemgetter
first_words = defaultdict(list)
for number, line in enumerate(getlines(filename), 1):
if line:
first_words[line.split(0)].append(number)
现在得到这些线:
itemgetter(*first_words['word3'])(getlines(filename))
我不认为使用 readlines() 真的是内存或时间问题。这是我在一个文件中使用的简短示例,该文件有4000行,每行至少包含600个字母。
import MyUtils as utils
LOGDIR = '/opt/lsf_events/7.0.6/work/blr_ifx/logdir/lsb.acct.1'
utils.Timer.start()
with open(LOGDIR,'r') as fHeader:
for line in fHeader.readlines():
if '1381671028' in line: #that particular number exists in the last line of the file.
print line
utils.Timer.end()
输出是...
Started Recording Time for the process...
"JOB_FINISH" "7.06" 1381671036 51303 22965 503578626 1 1381671028 0 0 1381671028 "umashank" "batch" "select[ ((type==X64LIN && osrel==50 && clearcase))]" "" "" "blrlc275" "/home/padbgl/spt9_m5p120_5v0_cm112/nodm/default/units/top/simulation/titan/FE/TPL_100_tx_top_new_ls" "" "" "" "1381671028.51303" 0 1 "blrlc275" 64 225.0 "" "/home/padbgl/bin/prjgate -e -- /home/umashank/.lsbatch/blrlc275.21758.0.1381671027.TITAN" 1.037842 0.119981 10116 0 -1 0 0 21997 0 0 0 0 -1 0 0 0 3735 82 -1 "" "padbgl_spt9_m5p120_5v0_cm112" 0 1 "" "" 0 3068 44332 "" "" "" "" 0 "" 0 "" -1 "/umashank" "" "" "" -1 "" "" 5136 "" 1381671028 "" "" 0
Process ended at : 15-10-13 08:02:56
Total time taken by the process is : 0:00:00.011601
希望您可以轻松地使用 readlines(),因为它花费的时间非常少,而且对于 3mb 的内存文件来说几乎是即时的。
这不是您所要求的替代方法,而只是试图告诉您,如果您使用典型的传统程序读取文件,不会有任何损坏。