0

让我更好地解释我的问题!我有一个这种格式的输入文件

word1 word2  
word3 word4 word5  
word4 word6

给定word3,我希望能够获得整行并获得word4和word5。

打开文件,可以解析每一行,但是我的文件很大,需要很长时间。有没有一种经济高效的方法可以做到这一点?

任何帮助表示赞赏!

4

3 回答 3

1

除非数据以某种可预测的方式排序(例如排序),否则您必须阅读每一行以找到相关的。

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 代码中)。

于 2013-10-15T01:22:11.263 回答
0

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))
于 2013-10-15T02:30:46.090 回答
0

我不认为使用 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 的内存文件来说几乎是即时的。

这不是您所要求的替代方法,而只是试图告诉您,如果您使用典型的传统程序读取文件,不会有任何损坏。

于 2013-10-15T02:39:16.407 回答