сопоставление всего списка с каждой строкой файла - PullRequest
0 голосов
/ 25 апреля 2019

Я написал фрагмент кода, который в основном выполняет поиск и замену из списка в текстовом файле.

Итак, он отображает весь список в словарь.Затем из текстового файла каждая строка обрабатывается и сопоставляется со всем списком в словаре, если в любом месте строки найдено совпадение, она заменяется соответствующим значением из списка (словаря).

Вот код:

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 ===> replaceword1

word2 ===> replaceword2

.....

Список разделен табуляцией.Здесь я использовал ===> для простоты понимания.

Входной файл:

hello word1 I am here.

word2. how are you word1?

Ожидаемый результат:

hello replaceword1 I am here.

replaceword2. how are you replaceword1?

Ответы [ 2 ]

2 голосов
/ 25 апреля 2019

Если ваш список слов достаточно мал, лучшее ускорение, которое вы можете достичь с помощью процесса сопоставления и замены, - это использовать одно большое регулярное выражение и использовать функционал 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
0 голосов
/ 25 апреля 2019

Почему бы вам не прочитать содержимое всего файла в строке, а просто сделать 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?
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...