Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/276.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在python中使用字典将字符串替换为id_Python_Dictionary - Fatal编程技术网

在python中使用字典将字符串替换为id

在python中使用字典将字符串替换为id,python,dictionary,Python,Dictionary,我有一个字典文件,每行包含一个单词 titles-sorted.txt a&a a&b a&c_bus a&e a&f a&m .... 对于每个单词,其行号是单词的id 然后我有另一个文件,它包含一组单词,每行用tab分隔 a、 文本 a_15 a_15_highway_(sri_lanka) a_15_motorway a_15_motorway_(germany)

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

titles-sorted.txt

 a&a    
 a&b    
 a&c_bus    
 a&e    
 a&f    
 a&m    
 ....
对于每个单词,其行号是单词的id

然后我有另一个文件,它包含一组单词,每行用tab分隔

a、 文本

 a_15   a_15_highway_(sri_lanka)    a_15_motorway   a_15_motorway_(germany) a_15_road_(sri_lanka)
如果字典中有id,我想用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()
但这段代码速度太慢了,所以如果我做的每件事都是对的,我会怀疑


这是一种有效的方法吗?

写入循环包含大量对
写入的调用,这些调用通常效率低下。通过每行只写一次(或者如果文件足够小,则每文件写一次),您可能可以加快速度

甚至:

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)}

因此,我怀疑这取决于您运行的操作系统和特定的python实现(比我更聪明的人可能会在这里提供一些澄清),但我怀疑发生了什么:

每次调用write时,所需的写入请求中的一部分都会写入缓冲区,一旦缓冲区已满,该信息就会写入文件。该文件需要从硬盘中提取(因为它不存在于主内存中)。因此,您的计算机在等待从硬盘获取数据块并写入数据块所需的几毫秒时间时会暂停。另一方面,您可以在几纳秒内解析字符串并查找hashmap,因此您需要花费大量时间等待写入请求完成

如果你没有立即写,而是保留了一个你想写的行的列表,然后只在最后一行写它们,或者如果你正在处理一个巨大的文件,它将超过你的主内存的容量,那么一旦你解析了一定数量的行,就写它


这允许优化磁盘写入,因为您可以一次写入多个块(同样,这取决于Python和操作系统如何处理写入调用)

如果我们应用到目前为止的建议并进一步清理您的代码(例如,删除不必要的.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()

如果仍然太慢,请给我们稍微多一些数据,包括两个输入文件中每一个文件的行数估计值。

有多少个键,然后替换多少个单词?一件事是,您调用的是
readlines
,您不需要它,这取决于您使用的python版本,这可能导致一次读取所有文件,这是不必要的。您可以简单地对f中的l使用
您考虑过使用线程和工作线程吗?它的速度应该是工作线程数的一倍。请注意:这不是对算法的评论。这只是一条语句,需要更多的工作人员才能更快地完成。@earnshae这段代码看起来应该按顺序处理行中的每一行和每一个标记,以便在输出文件中保持顺序,所以我不知道如何在其中包含线程。另一件事是,您要单独编写每个标记。您可以通过只写几行甚至一次写出完整的结果来改进。我将发布一个关于删除#个fw.write()调用显著降低了速度的答案,现在代码运行速度非常快。谢谢但是我认为title\u map中的
token[0]和title\u map.keys()中的
token[0]是等价的。显式调用keys()是否更昂贵?“in-map”是哈希时间查找。“in map.keys()”取决于python版本。在Python 2中,它是列表的线性搜索。在Python3中,是对dict_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()