我有一个字典文件,每行包含一个单词。
标题-sorted.txt
a&a
a&b
a&c_bus
a&e
a&f
a&m
....
对于每个单词,其行号是单词的id。
然后我有另一个文件,其中包含由每行中的制表符分隔的一组单词。
a.txt
a_15 a_15_highway_(sri_lanka) a_15_motorway a_15_motorway_(germany) a_15_road_(sri_lanka)
如果字典中存在,我想用id替换所有单词,以便输出看起来像,
3454 2345 123 5436 322 ....
所以我编写了这样的python代码来执行此操作:
f = open("titles-sorted.txt")
lines = f.readlines()
titlemap = {}
nr = 1
for l in lines:
l = l.replace("\n", "")
titlemap[l.lower()] = nr
nr+=1
fw = open("a.index", "w")
f = open("a.txt")
lines = f.readlines()
for l in lines:
tokens = l.split("\t")
if tokens[0] in titlemap.keys():
fw.write(str(titlemap[tokens[0]]) + "\t")
for t in tokens[1:]:
if t in titlemap.keys():
fw.write(str(titlemap[t]) + "\t")
fw.write("\n")
fw.close()
f.close()
但是这段代码速度非常慢,所以如果我做的一切都做对了,我就会产生怀疑。
这是一种有效的方法吗?
答案 0 :(得分:4)
写循环包含许多对write
的调用,这些调用通常效率低下。您可以通过每行只写一次(或者如果文件足够小,每个文件一次)来加快速度。
tokens = l.split("\t")
fw.write('\t'.join(fw.write(str(titlemap[t])) for t in tokens if t in titlemap)
fw.write("\n")
甚至:
lines = []
for l in f:
lines.append('\t'.join(fw.write(str(titlemap[t])) for t in l.split('\t') if t in titlemap)
fw.write('\n'.join(lines))
此外,如果您的令牌被多次使用,您可以在阅读时将它们转换为字符串来节省时间:
titlemap = {l.strip().lower(): str(index) for index, l in enumerate(f, start=1)}
答案 1 :(得分:1)
所以,我怀疑这会因你运行的操作系统和特定的python实现而有所不同(有人比我能提供一些澄清的人更聪明),但我怀疑会发生什么于:
每次调用write时,会将一些所需的写入请求写入缓冲区,然后一旦缓冲区已满,就会将此信息写入文件。需要从硬盘中提取文件(因为它不存在于主内存中)。因此,当计算机等待从硬盘获取块并写入块所花费的几毫秒时,计算机会暂停。另一方面,你可以在几纳秒内解析字符串和查找你的hashmap,所以你花了很多时间等待写请求完成!
而不是立即写作,如果你改为保存一个你想要写的行的列表,然后只在最后写入它们,连续写入,或者如果你正在处理一个巨大的文件,该怎么办?这将超过主内存的容量,一旦解析了一定数量的行就写下来。
这允许优化写入磁盘,因为您可以一次写入多个块(同样,这取决于Python和操作系统如何处理写入调用)。
答案 2 :(得分:0)
如果我们到目前为止应用这些建议并再清理一下代码(例如删除不必要的.keys()调用),以下内容对您的需求是否仍然太慢?
title_map = {}
token_file = open("titles-sorted.txt")
for number, line in enumerate(token_file):
title_map[line.rstrip().lower()] = str(number + 1)
token_file.close()
input_file = open("a.txt")
output_file = open("a.index", "w")
for line in input_file:
tokens = line.split("\t")
if tokens[0] in title_map:
output_list = [title_map[tokens[0]]]
output_list.extend(title_map[token] for token in tokens[1:] if token in title_map)
output_file.write("\t".join(output_list) + "\n")
output_file.close()
input_file.close()
如果它仍然太慢,请为我们提供更多数据,包括估算两个输入文件中每行的行数。