Страницы

Поиск по вопросам

пятница, 28 февраля 2020 г.

Как сделать, чтобы моя функция set_checkpoints() корректно обрабатывала текстовый файл

#python #python_3x


У меня есть текстовый файл data.txt:

яблоко
банан
абрикос
яблоко
апельсин
апельсин
мандарин 
абрикос
абрикос
абрикос
абрикос
абрикос


Я пытаюсь сделать так, чтобы после обработки файла data.txt  функцией set_checkpoints()
на выходе получался файл save.txt:

//А//яблоко//А//   
//А//банан//А// 
//А//абрикос//А//
//А//яблоко//А//
//А//апельсин//А//
//А//апельсин//А// 
//А//мандарин//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//
//А//абрикос//А//


Но в результате у меня получается вот что:

//А//яблоко//А//
//А//банан//А//
//А//абрикос//А//
яблоко
//А//апельсин//А//
апельсин
//А//мандарин//А// 
абрикос
абрикос
абрикос
абрикос
абрикос


Решение:
Нужно сделать так, чтобы функция при нахождении нужного слова из массива, продолжил
поиск данного слова до конца файла, а не прерывался на первом же совпадении и переходил
бы к следующему слову. В итоге у меня получается, что он находит из массива fruits
совпадение со словом из текстового файла, отмечает его чекпойтами и переходит к поиску
следующего слова из массива. Как сделать так, чтобы функция работала корректно? 

Вот мой код: 

import re

path = 'data.txt' # input data
save = 'save.txt' # output data

def open_read(path): # функция открывает и считывает файл
    file = open(path, 'r')
    content = file.read()
    file.close()
    #print(content)
    return content


Fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов

n=len(Fruits) # определение размера массива Fruits

def set_checkpoints(content): # функция устанавливает checkpoints
    for i in range(n):
        find = re.compile(Fruits[i])
        res = find.search(content)
        #lenght = len(find.findall(content)) # определяет общее количество конкретного
найденного слова
        #print (lenght)
        #for i in range(lenght):
        if res == None: continue #  Если не обнаружено слово
        else:
            k1 = res.start()
            k2 = res.end()
            content = content[:k1]+"//А//"+content[k1:k2]+"//А//"+content[k2:]
    print(content)
    return content
###############################################

content = open_read(path) # окрываем файл
content = set_checkpoints(content) # обрабатываем файл функцией set_checkpoints()

file = open(save, 'w') # сохраняем файл
file.write(content)
file.close()


P.S.
Я так понимаю тут дело заключается в методе search(), т.к. метод search() ищет по
всей строке, но возвращает только первое найденное совпадение. Тут похоже нужно использовать
метод findall(), т.к. этот метод возвращает список всех найденных совпадений. Но я
не знаю, как в findall() реализовать установку чекпоинтов. Свойства start() и end()
работают только в методе search(). 

Помогите, пожалуйста.
    


Ответы

Ответ 1



Не нужны тут регулярные выражения: fruits = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин'] with open('input.txt', encoding='utf-8') as f_in: with open('output.txt', 'w', encoding='utf-8') as f_out: for line in f_in: # Для удаления справа пустых символов: ' ', '\n', '\r', и т.п. line = line.rstrip() # Если фрукт есть в списке if line in fruits: f_out.write('//А//{}//А//\n'.format(line)) Если работать с текстом и через функцию: FRUITS = ['яблоко', 'банан', 'абрикос', 'апельсин', 'мандарин'] def set_checkpoints(text: str) -> str: # В одну строку return '\n'.join( '//А//{}//А//'.format(line) for line in text.splitlines() if line in FRUITS ) # NOTE: тот же код, что выше # new_lines = [] # # for line in text.splitlines(): # if line in FRUITS: # new_lines.append('//А//{}//А//'.format(line)) # # return '\n'.join(new_lines) with open('input.txt', encoding='utf-8') as f: content = f.read() # Обрабатываем файл функцией set_checkpoints() content = set_checkpoints(content) with open('output.txt', 'w', encoding='utf-8') as f: f.write(content) Результат (output.txt): //А//яблоко//А// //А//банан//А// //А//абрикос//А// //А//яблоко//А// //А//апельсин//А// //А//апельсин//А// //А//мандарин//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А//

Ответ 2



Если планируется обрабатывать небольшие файлы (заведомо меньшие половины свободной оперативной памяти), то можно заменять текст без циклов: import re from pathlib import Path fruits = ['яблоко','банан','абрикос','апельсин','мандарин'] # массив ключевых слов pref, suff = '//А//', '//А//' text = Path(r'D:\temp\1.txt').read_text(encoding='utf-8') pat = r'(\b)({})(\b)'.format('|'.join(fruits)) text = re.sub(pat, r'\1{}\2{}\3'.format(pref, suff), text) Path(r'D:\temp\result.txt').write_text(text, encoding='utf-8') # check print(Path(r'D:\temp\result.txt').read_text(encoding='utf-8')) результат: //А//яблоко//А// //А//банан//А// //А//абрикос//А// //А//яблоко//А// //А//апельсин//А// //А//апельсин//А// //А//мандарин//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А// //А//абрикос//А//

Комментариев нет:

Отправить комментарий