【问题标题】:matching an entire list with each and every line of file将整个列表与文件的每一行匹配
【发布时间】:2019-09-14 12:47:18
【问题描述】:

我写了一段代码,基本上是从文本文件的列表中执行查找和替换。

因此,它将整个列表映射到字典中。然后从文本文件中处理每一行,并与字典中的整个列表匹配,如果在该行中的任何位置找到匹配项,它将替换为列表(字典)中的相应值。

代码如下:

import sys
import re

#open file using open file mode
fp1 = open(sys.argv[1]) # Open file on read mode
lines = fp1.read().split("\n") # Create a list containing all lines
fp1.close() # Close file


fp2 = open(sys.argv[2]) # Open file on read mode
words = fp2.read().split("\n") # Create a list containing all lines
fp2.close() # Close file

word_hash = {}

for word in words:
    #print(word)
    if(word != ""):
        tsl = word.split("\t")
        word_hash[tsl[0]] = tsl[1]

#print(word_hash)
keys = word_hash.keys()
#skeys = sorted(keys, key=lambda x:x.split(" "),reverse=True)
#print(keys)
#print (skeys)

for line in lines:
    if(line != ""):
        for key in keys:
            #my_regex = key + r"\b"
            my_regex = r"([\"\( ])" + key + r"([ ,\.!\"।)])"
            #print(my_regex)
            if((re.search(my_regex, line, re.IGNORECASE|re.UNICODE))):
                line = re.sub(my_regex, r"\1" + word_hash[key]+r"\2",line,flags=re.IGNORECASE|re.UNICODE|re.MULTILINE)
                #print("iam :1",line)
            if((re.search(key + r"$", line, re.IGNORECASE|re.UNICODE))):
                line = re.sub(key+r"$", word_hash[key],line,flags=re.IGNORECASE|re.UNICODE|re.MULTILINE)
                #print("iam :2",line)
            if((re.search(r"^" + key, line, re.IGNORECASE|re.UNICODE))):
                #print(line)
                line = re.sub(r"^" + key, word_hash[key],line,flags=re.IGNORECASE|re.UNICODE|re.MULTILINE)
                #print("iam :",line)
        print(line)
    else:
        print(line)

这里的问题是当列表大小增加时,执行速度会变慢,因为文本文件的所有行都与列表中的每个键匹配。那么我在哪里可以改进这段代码的执行呢。

列表文件:

word1===>替换word1

word2===>替换word2

.....

列表是制表符分隔的。为了便于理解,这里我使用了 ===>。

输入文件:

hello word1 I am here.

word2. how are you word1?

预期输出:

hello replaceword1 I am here.

replaceword2. how are you replaceword1?

【问题讨论】:

  • 您能发布示例输入文件和预期输出吗?
  • 添加样本输入输出@Rakesh
  • 我有很多输入文件,每个文件在 100 到 200 行之间,从 8K 到 20 K
  • 将整个文本读入内存,替换单词并保存回来应该是最简单的!在@Nagaraju 下方查看我的答案

标签: regex python-3.x performance dictionary


【解决方案1】:

如果您的单词列表足够小,您可以通过匹配和替换过程实现的最佳加速是使用单个大正则表达式并使用函数re.sub

这样你就可以对优化函数进行一次调用。

编辑:为了保留替换顺序(这可能导致链替换,不知道是否预期行为)我们可以按批次执行替换,而不是在一次运行中执行替换,其中批次顺序尊重文件顺序和每个批次由不相交的可能字符串匹配组成。

代码如下

import sys
import re


word_hashes = []

def insert_word(word, replacement, hashes):
    if not hashes:
        return [{word: replacement}]
    for prev_word in hashes[0]:
        if word in prev_word or prev_word in word:
            return [hashes[0]] + insert_word(word, replacement, hashes[1:])
    hashes[0][word] = replacement
    return hashes

with open(sys.argv[2]) as fp2: # Open file on read mode
    words = fp2.readlines()
    for word in [w.strip() for w in words if w.strip()]:
        tsl = word.split("\t")
        word_hashes = insert_word(tsl[0],tsl[1], word_hashes)

#open file using open file mode
lines = []
with open(sys.argv[1]) as fp1:
    content = fp1.read()
    for word_hash in word_hashes: 
        my_regex = r"([\"\( ])(" + '|'.join(word_hash.keys()) + r")([ ,\.!\"।)])"
        content = re.sub(my_regex, lambda x: x.group(1) + word_hash[x.group(2)] + x.group(3) ,content,flags=re.IGNORECASE|re.UNICODE|re.MULTILINE)

print(content)

我们获得了示例数据的链式替换。比如用下面的词来代替

roses are red==>flowers are blue
are==>is

要解析的文本

roses are red and beautiful
flowers are yellow

输出

roses is red and beautiful
flowers is yellow

【讨论】:

  • 替换时字典顺序没有保留吗?
  • 我不明白,字典只能有一个给定键的条目,那么为什么顺序很重要?
  • 场景,列表文件:玫瑰是红色的=>花是蓝色的,是=>是,输入文件:玫瑰是红色的,非常漂亮。\n玫瑰是蓝色的。这里的玫瑰是红色的不会被替换
  • 好的,我明白了。好吧,我想您必须在这些边缘情况下在性能和保持文件顺序之间做出选择……我没有看到一种快速的方法来满足更高效且不需要几个小时的开发的要求。
  • 通过适当的开发,您可以两全其美。这个想法是更巧妙地构建密钥数据结构。而不是一个字典,你必须有一个字典列表。当您插入要替换的键时,您将首先检查第一个字典中是否还没有作为子字符串的键,否则插入以下字典。然后,您可以按顺序使用此方法替换每个 dict。如果我有时间,我会在今天晚些时候制作一个 sn-p。
【解决方案2】:

你为什么不把整个文件的内容读成一个字符串,然后string.replace。例如。

def find_replace():

    txt = ''
    #Read text from the file as a string
    with open('file.txt', 'r') as fp:
        txt = fp.read()

    dct = {"word1":"replaceword1","word2":"replaceword2"}

    #Find and replace characters
    for k,v in dct.items():
        txt = txt.replace(k,v)

    #Write back the modified string
    with open('file.txt', 'w') as fp:
        fp.write(txt)

如果输入文件是:

hello word1 I am here.

word2. how are you word1?

输出将是:

hello replaceword1 I am here.

replaceword2. how are you replaceword1?

【讨论】:

  • 不会在任何找到匹配项的地方替换,例如应该有空格或任何双引号,或者它可能是字符串的开头但不是其他任何地方。
  • 不,它会在更大的文件中找到要替换的确切原始字符串,并且只替换那个词!我正在从带有空格和换行符的文件中读取完整的字符串。试一试一些例子,看看会不会出错!
  • 它在 unicode 文本上失败。文本=HTML इमेजेस(图像),列表=इमेज=>图像。所以这里的 unicode 文本不应该被替换,而是替换为 HTML 图像ेस(图像)
  • 您可以修改字典以正确替换非纯英语的 unicode 文本!
  • 我认为你不明白我在说什么。对于 unciode 文本,即使它是单词的一部分,它也会被替换,理想情况下不应该发生这种情况
猜你喜欢
  • 2011-08-15
  • 2013-08-01
  • 2019-11-19
  • 2020-11-23
  • 2020-11-24
  • 1970-01-01
  • 1970-01-01
  • 2020-02-07
  • 2020-11-12
相关资源
最近更新 更多