从词汇表中替换字符串的有效方法-Python

从词汇表中替换字符串的有效方法-Python,python,regex,multithreading,python-multithreading,Python,Regex,Multithreading,Python Multithreading,我有一个短语词汇表,我想用这些单词替换另一个文件中的单词。例如,我有以下词汇表: 美国,, 纽约 我想替换以下文件: “我在纽约工作,但我甚至不住在美国” 为此: “我在纽约工作,但我甚至不住在美国” 目前我正在这样做: import os def _check_files_and_write_phrases(docs, worker_num): print("worker ", worker_num," started!") for i, file in enumerate(

我有一个短语词汇表,我想用这些单词替换另一个文件中的单词。例如,我有以下词汇表:

美国,, 纽约

我想替换以下文件:

“我在纽约工作,但我甚至不住在美国”

为此:

“我在纽约工作,但我甚至不住在美国”

目前我正在这样做:

import os

def _check_files_and_write_phrases(docs, worker_num):
    print("worker ", worker_num," started!")
    for i, file in enumerate(docs):
        file_path = DOCS_FOLDER + file
        with open(file_path) as f:
            text = f.read()
            for phrase in phrases:
                text = text.replace(phrase, phrase.replace(' ','_'))
            new_doc = PHRASES_DOCS_FOLDER + file[:-4] + '_phrases.txt'
            with open(new_doc, 'w') as nf:
                nf.write(text)

    print("job done on worker ", worker_num)


docs = os.listdir(DOCS_FOLDER)

import threading

threads = []
for i in range(1, 11):
    print(i)
    start = int((len(docs)/10) * (i - 1))
    end = int((len(docs)/10) * (i))
    print(start,end)
    if i != 10:
        t = threading.Thread(target=_check_files_and_write_phrases, args=(docs[start:end], i, ))
    else:
        t = threading.Thread(target=_check_files_and_write_phrases, args=(docs[start:], i, ))
    threads.append(t)
    t.start()

for t in threads:
    t.join()

print("all workers finished!")
但是太慢了!我以为线程可以完成任务,但我错了


是否有另一种有效的方法执行此操作?

尝试更改
for
循环,以仅替换文本中存在的短语:

for phrase in set(phrases).intersection(text.split()):
...

无论是否使用线程,都可以尝试使用。

可以使用单个
re.sub()
调用替换所有短语,该调用可以预编译以进一步加快速度:

import re

phrases = {"United States":"United_States", "New York":"New_York"}
re_replace = re.compile(r'\b({})\b'.format('|'.join(re.escape(phrase) for phrase in phrases.keys())))

def _check_files_and_write_phrases(docs, worker_num):
    print("worker {} started!".format(worker_num))

    for i, filename in enumerate(docs):
        file_path = DOCS_FOLDER + filename

        with open(file_path) as f:
            text = f.read()
            text = re_replace.sub(lambda x: phrases[x.group(1)], text)
            new_doc = PHRASES_DOCS_FOLDER + filename[:-4] + '_phrases.txt'

            with open(new_doc, 'w') as nf:
                nf.write(text)

    print("job done on worker ", worker_num)
这首先创建一个正则表达式,以便根据短语词典进行搜索,如下所示:

\b(United\ States|New\ York)\b
re.sub()
函数然后使用
短语
字典查找所需的短语替换。它包含两个参数,替换和原始文本。替换可以是固定字符串,也可以是使用函数。该函数接受匹配对象的单个参数,并返回替换文本。一个
lambda
函数用于执行此操作,它只需在
phrases
字典中查找匹配对象


它可以在这里使用
replace()
,而不是进行字典查找,但是预先计算的替换文本应该更快。添加的
\b
仅用于替换单词边界上的内容,因此将跳过例如
mynewyork
。如果需要,将
flags=re.I
添加到
re.compile()
可用于使搜索不区分大小写。

如果导入re,它具有搜索短语的特定功能。阅读这里的正则表达式操作符:@DeathPox我认为问题不在于str.replace()函数,而是我使用它的方式。尽管如此,我仍将测试re.replace,并使用一些文件比较处理时间。谢谢你的建议。由于恐惧,你的代码不能并行执行(除了加载文件部分)。改用,但仅当瓶颈是处理(即输入文件或短语列表太大)时才使用。此外,根据文件或短语列表的大小,逐行读取文件并逐行检查所有短语可能比将整个文件加载到内存中并替换其中匹配的短语更快。@zwer谢谢,大大提高了性能。您能解释一下“短语[x.group(1)]”的作用吗?
x.group(1)
-
x
是一个匹配对象,找到的文本是
组(1)
phrases[]
是短语词典,因此实际上它会在词典中查找一些文本,并返回要替换的文本。我没有发现使用您的方法在性能上有很大提高,但我与@zwer注释合并使用了多处理而不是线程,现在它的处理速度更快了。无论如何,谢谢你。