我有一个文件,每行包含人名和包含演讲文本的文件。具有名称的文件非常大(250k行)按字母顺序排序,语音文件大约有1k行。我想要做的是查找我的文本文件中的名称,并从我的名称文件中替换每个出现的名称。 这是我的代码编辑:打开列表的with函数只执行一次。
members_list = []
with open(path, 'r') as l:
for line in l.readlines():
members_list.append(line.strip('\n'))
for member in self.members_list:
if member in self.body:
self.body = self.body.replace(member, '<member>' + member + '</member>')
此代码运行大约需要2.2秒,但因为我有很多语音文件(4.5k),所以总时间大约为3小时。 是否有可能加快速度?发电机是否可行?
答案 0 :(得分:1)
目前,当您检查&#34;如果成员在self.body&#34;。
时,您会为250,000个名称中的每一个重读一次内存中的每个语音。你需要解析一次语音体,找到整个单词,空格和标点符号。然后,您需要查看是否找到了名称,使用已知成员名称的线性时间查找,或者在最差的日志时间。
问题是你必须找到具有不同字长的成员名称。所以这是一个快速(并不是很好)的实现,我写了来处理检查最后三个单词。
# This is where you load members from a file.
# set gives us linear time lookup
members = set()
for line in ['First Person', 'Pele', 'Some Famous Writer']:
members.add(line)
# sample text
text = 'When Some Famous Writer was talking to First Person about Pele blah blah blah blah'
from collections import deque
# pretend we are actually parsing, but I'm just splitting. So lazy.
# This is why I'm not handling punctuation and spaces well, but not relevant to the current topic
wordlist = text.split()
# buffer the last three words
buffer = deque()
# TODO: loop while not done, but this sort of works to show the idea
for word in wordlist:
name = None
if len(buffer) and buffer[0] in members:
name = buffer.popleft()
if not name and len(buffer)>1:
two_word_name = buffer[0] + ' ' + buffer[1]
if two_word_name in members:
name = two_word_name
buffer.popleft()
buffer.popleft()
if not name and len(buffer)>2:
three_word_name = buffer[0] + ' ' + buffer[1] + ' ' + buffer[2]
if three_word_name in members:
name = three_word_name
buffer.popleft()
buffer.popleft()
buffer.popleft()
if name:
print ('<member>', name, '</member> ')
if len(buffer) >2:
print (buffer.popleft() + ' ')
buffer.append(word)
# TODO handle the remaining words which are still in the buffer
print (buffer)
我只是想证明这个概念。这不会处理空格或标点符号。这根本没有处理结束 - 它需要在没有完成的情况下循环。它在解析时会创建一堆临时字符串。但它说明了解析一次的基本概念,即使在解析语音文本时速度非常慢,也可能超过搜索语音文本250,000次。
您要解析文本并检查集中名称的原因是您执行此操作一次。集合具有分摊的线性时间查找,因此检查成员中的名称是否更快。
如果我有机会,我可能会稍后编辑它,成为一个生成令牌的类,并在最后修复查找名称,但我并不打算将其作为您的最终代码。