我有一个文件,每行包含人名和包含演讲文本的文件。具有名称的文件非常大(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小时。是否有可能加快速度?发电机是否可行?
目前,当您检查“是否为self.body中的成员”时,您会为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次。
您要解析文本并检查集中名称的原因是您执行此操作一次。集合具有分摊的线性时间查找,因此检查成员中的名称是否更快。
如果我有机会,我可能稍后编辑它是一个生成令牌的类,并在最后修复查找名称,但我不打算这是你的最终代码。