Python добавить пробел - PullRequest
       11

Python добавить пробел

0 голосов
/ 24 октября 2019

У нас есть повторяющиеся слова, такие как мистер и миссис в тексте. Мы хотели бы добавить пробел до и после ключевых слов Mr и Mrs. Но слово Mr становится повторяющимся в Mrs. Пожалуйста, помогите в решении вопроса:

Ввод:

Hi ThisМистер СэмЗдравствуйте, это MrsPamela.Mr.Sam, о чем вы звоните? Миссис Памела, у меня к вам вопрос.

import re

s = "Hi This is Mr Sam. Hello, this is Mrs.Pamela.Mr.Sam, what is your call about? Mrs. Pamela, I have a question for you."
words = ("Mr", "Mrs")


def add_spaces(string, words):

for word in words:
    # pattern to match any non-space char before the word
    patt1 = re.compile('\S{}'.format(word))

    matches = re.findall(patt1, string)
    for match in matches:
        non_space_char = match[0]
        string = string.replace(match, '{} {}'.format(non_space_char, word))

    # pattern to match any non-space char after the word
    patt2 = re.compile('{}\S'.format(word))
    matches = re.findall(patt2, string)
    for match in matches:
        non_space_char = match[-1]
        string = string.replace(match, '{} {}'.format(word, non_space_char))

return string


print(add_spaces(s, words))

Текущий результат:

Hi This is Mr .Sam. Hello, this is Mr sPamela. Mr .Sam, what is your call about? Mr s.Pamela, I have a question for you.

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

Hi This is Mr .Sam. Hello, this is Mrs Pamela. Mr .Sam, what is your call about? Mrs .Pamela, I have a question for you.

Ответы [ 2 ]

0 голосов
/ 24 октября 2019

Я не очень хорошо разбираюсь в модуле re, но я нашел решение, которое можно расширить на любое количество слов и строк и которое отлично работает (протестировано в python3), хотя, вероятно, оно очень обширное. и вы можете найти что-то более оптимизированное и гораздо более краткое. С другой стороны, не очень сложно понять процедуру:

  1. Для начала программа упорядочивает список слов по убыванию.
  2. Затем находит совпадениясначала из более длинных слов и принимает к сведению разделы, где совпадения уже были сделаны, чтобы не менять их снова. (Обратите внимание, что это вводит ограничение, но это необходимо, поскольку программа не может знать, хотите ли вы разрешить, чтобы слово в переменном слове могло содержаться в другом, в любом случае это не влияет на ваш случай)
  3. Когда он принял к сведению все совпадения (в неблокированной части строки) слова, он добавляет соответствующие пробелы и исправляет заблокированные индексы (они сместились из-за вставки пробелов)
  4. Наконец, выполняется обрезка для удаления нескольких пробелов

Примечание: я использовал список переменных слов вместо кортежа

import re

def add_spaces(string, words):
    # Get the lenght of the longest word
    max_lenght = 0
    for word in words:
        if len(word)>max_lenght:
            max_lenght = len(word)
    print("max_lenght = ", max_lenght)

    # Order words in descending lenght
    ordered_words = []
    i = max_lenght
    while i>0:
        for word in words:
            if len(word)==i:
                ordered_words.append(word)
        i -= 1
    print("ordered_words = ", ordered_words)

    # Iterate over words adding spaces with each match and "blocking" the match section so not to modify it again
    blocked_sections=[]
    for word in ordered_words:
        matches = [match.start() for match in re.finditer(word, string)]
        print("matches of ", word, " are: ", matches)

        spaces_position_to_add = []
        for match in matches:
            blocked = False
            for blocked_section in blocked_sections:
                if match>=blocked_section[0] and match<=blocked_section[1]:
                    blocked = True
            if not blocked:
                # Block section and store position to modify after
                blocked_sections.append([match,match+len(word)])
                spaces_position_to_add.append([match,match+len(word)+1])

        # Add the spaces and update the existing blocked_sections
        spaces_added = 0
        for new_space in spaces_position_to_add:
            # Add space before and after the word
            string = string[:new_space[0]+spaces_added]+" "+string[new_space[0]+spaces_added:]
            spaces_added += 1
            string = string[:new_space[1]+spaces_added]+" "+string[new_space[1]+spaces_added:]
            spaces_added += 1

            # Update existing blocked_sections
            for blocked_section in blocked_sections:
                if new_space[0]<blocked_section[0]:
                    blocked_section[0] += 2
                    blocked_section[1] += 2

    # Trim extra spaces
    string = re.sub(' +', ' ', string)

    return string


###  MAIN  ###
if __name__ == '__main__':
    s = "Hi This is Mr Sam. Hello, this is Mrs.Pamela.Mr.Sam, what is your call about? Mrs. Pamela, I have a question for you."
    words = ["Mr", "Mrs"]

    print(s)
    print(add_spaces(s,words))
0 голосов
/ 24 октября 2019

Вы не указали ничего после буквы 'r', поэтому ваш шаблон будет соответствовать любому, начинающемуся с пробела, за которым следуют 'M' и 'r', поэтому он будет захватывать любой 'Mr', даже если за ним следует's', такие как Mrs, поэтому ваш первый шаблон добавляет пробел в середине Mrs.

Лучшим шаблоном будет r'\bMr\b'

'\b', фиксирующий границы слов, см. Документ для дальнейших объяснений: https://docs.python.org/3/library/re.html

...