首页 > 解决方案 > 用python中的搭配字典替换文本文件中的所有搭配

问题描述

我正在尝试使用 python 将文本文件 [corpus.txt] 中的子字符串替换为其他一些子字符串 [collocation|ngram]。我在包含以下内容的文件 sub.txt 中有可能的子字符串列表:

dogs chase
birds eat
chase birds
chase cat
chase birds .

和一个 corpus.txt 包含一些文本如下:

dogs chase cats around
dogs bark
cats meow
dogs chase birds
cats chase birds , birds eat grains
dogs chase the cats
the birds chirp

具有所需的输出

<bop> dogs chase <eop> cats around
dogs bark
cats meow
<bop> dogs chase <eop> birds 
cats <bop> chase birds <eop> , <bop> birds eat <eop> grains
<bop> dogs chase <eop> the cats
the birds chirp

还有我的带有多处理的python代码(由于 and 的大小而使用了多corpus处理sub

import sys
import string
import time
from multiprocessing import Pool
import re
import itertools
flatten = itertools.chain.from_iterable

#corpus_dir =  sys.argv[1]
#ngram_dir = sys.argv[2]

#f = open(corpus_dir) # Open file on read mode
#corpus = f.read().split("\n") # Create a list containing all lines
#f.close() # Close file

#f2 = open(ngram_dir) # Open file on read mode
#sub = f2.read().split("\n") # Create a list containing all lines
#f2.close() # Close file

sub = ['dogs chase', 'birds eat', 'chase birds', 'chase cat', 'chase birds .']
corpus = [' dogs chase cats around ', ' dogs bark ', ' cats meow ', ' dogs chase birds ', ' cats chase birds , birds eat grains ', ' dogs chase the cats ', ' the birds chirp ']
print("The corpus has ", len(corpus))


sbsx = { " "+ng+" " : " <bop> "+ng+" <eop> " for ng  in sub }
def multiple_replace(string, rep_dict):
     pattern = re.compile("|".join([re.escape(k) for k in sorted(rep_dict,key=len,reverse=True)]), flags=re.DOTALL)
     print("replaced = ")
     return pattern.sub(lambda x: rep_dict[x.group(0)], string)

def f(a_list):
    out = [multiple_replace(sent, sbsx) for sent in a_list]
    '''out = []
    for sent in a_list:
      c = multiple_replace(sent, sbsx)
      out.append(c)
      #print(c)
      time.sleep(0.01)
'''
    return out

def f_amp(a_list):
    #chunks = [a_list[i::5] for i in range(5)]
    chunks = [a_list[x:x+5] for x in range(0, len(a_list), 5)]
    print(len(chunks))

    pool = Pool(processes=10)

    result = pool.map_async(f, chunks)

    while not result.ready():
        print("Running...")
        time.sleep(0.5)

    return list(flatten(result.get()))


final_anot = f_amp(corpus)
print(final_anot)

我添加了已经初始化corpussub变量(在上面的代码片段中)来展示代码是如何工作的。在实际设置中,两者都corpus.txt包含sub.txt数百万行(分别为 200M+ 和 4M+)。我需要一个可以有效完成任务的代码,我已经尝试过Multiprocessingpool但需要数周才能完成。还有其他有效和快速的方法来完成这项任务吗?

标签: pythonpython-3.xnlpnltkinformation-retrieval

解决方案


您正在为每个句子重新编译您的模式。这需要相当多的时间。相反,您可以在全局范围内编译您的模式一次:

sbsx = { " "+ng+" " : " <bop> "+ng+" <eop> " for ng  in sub }
pattern = re.compile("|".join([re.escape(k) for k in sorted(sbsx,key=len,reverse=True)]), flags=re.DOTALL)

def multiple_replace(string):
     print("replaced = ")
     return pattern.sub(lambda x: sbsx[x.group(0)], string)

我用你的例句测试了 100 万次,我从 52 秒到只有 13 秒。

我希望我没有错过任何东西,这将有助于加快您的代码速度。


推荐阅读