使用Python加速使用dict键进行字符串搜索

时间:2015-01-13 12:15:16

标签: python dictionary

我已经开发了一些工作代码,但它的方法非常慢。我正在尝试使用我的字典键作为搜索字符串来搜索1000个字符串的大文本文件。

这是我的工作代码......

for root, subFolders, files in os.walk(path):
    for filename in files:  
        if filename.endswith('.txt'): 
            with open(os.path.join(root, filename), 'r') as f:
                print '\tProcessing file: '+filename


                for line in f:
                    if 'KEY_FRAME details' in line:
                        chunk = [next(f) for x in xrange(5)]
                        FRAME = chunk[5].split()
                        FRAME = FRAME[2]

                        framelist.append([FRAME])

            newdict = dict([(d[0], d[1:]) for d in framelist])

            f.close()

            with open(os.path.join(root, filename), 'r') as f:
                for line in f:
                    if any(['FRAME = '+str(i) in line for i in newdict.keys()]):
                        ...do more text processing based on following lines and append to frame key...

txt文件太大而无法直接读入内存,因此我对同一个文件执行两次搜索,第一次搜索是根据特定字符串标题'KEY_FRAME'收集感兴趣的帧编号,并将找到的帧放入一个列表。然后我使用帧号作为键将此列表转换为dict并关闭文件。

然后我重新打开文件并根据新的搜索字符串'FRAME ='+ str(帧编号)搜索文件中每行的'任意'字典键('帧编号') 。但是虽然该方法有效,但速度非常慢。

在初始文件读取期间,我曾想过某种搜索字符串切换,但是某些'FRAME ='+ str(帧编号)字符串出现在文件中的初始'KEY_FRAME details'字符串之前

对于上述(尽管是基本的)代码,是否有更有效的方法?

感谢阅读。

在查看建议的正则表达式解决方案后,我已将脚本的结尾更改为以下内容...

                        framelist.append(str(FRAME))


                f.seek(0)

                framed = re.compile('|'.join(framelist))
                framed = framed.pattern

                sentences = f
                for s in sentences:
                    if any(('FrameNumber = '+f) in s for f in framelist):
                        print 'first found'

                    if any(('FN = '+f) in s for f in framelist):
                        print 'second found'

最新增加的处理速度有一些改进(每个日志3分钟),所以可以容忍,虽然我希望稍微好一点,但是我每次都要搜索超过6000帧数。

1 个答案:

答案 0 :(得分:0)

您可以采取一些措施来提高速度。

1)不要关闭&重新打开文件:您可以使用f.seek(0)

将文件指针倒回到开头

2)您正在为第二个for line in f:循环中检查的每一行重建字符串列表。你应该在循环之外做到这一点,例如

keys = ['FRAME = '+str(i) for i in newdict.keys()]

甚至

keys = ['FRAME = '+i for i in newdict.keys()]

因为我认为newdict的密钥已经是字符串。

然后你的测试就会变成

if any(key in line for key in keys):

该测试使用的是生成器表达式而不是列表推导,因此any()可以在找到匹配后立即挽救,这通常比构建整个列表更快 在测试它们之前的比赛。

实际上,您可以使用正则表达式改进此匹配过程,如this answer中所示。