在python中使用字典替换带有id的字符串

时间:2016-01-22 16:14:54

标签: python dictionary

我有一个字典文件,每行包含一个单词。

标题-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()

但是这段代码速度非常慢,所以如果我做的一切都做对了,我就会产生怀疑。

这是一种有效的方法吗?

3 个答案:

答案 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()

如果它仍然太慢,请为我们提供更多数据,包括估算两个输入文件中每行的行数。