Эффективное использование .replace для текста - PullRequest
0 голосов
/ 14 июня 2019

Я пытаюсь использовать все слова в тексте, которые появляются только один раз.У меня есть бит, который находит, какие слова появляются только один раз, но когда я иду, чтобы заменить оригинальное слово версией .upper, куча других вещей также становится заглавной.Это небольшая программа, так что вот код.

from collections import Counter
from string import punctuation

 path = input("Path to file: ")
 with open(path) as f:
    word_counts = Counter(word.strip(punctuation) for line in f for word in line.replace(")", " ").replace("(", " ")
                      .replace(":", " ").replace("", " ").split())

wordlist = open(path).read().replace("\n", " ").replace(")", " ").replace("(", " ").replace("", " ")

unique = [word for word, count in word_counts.items() if count == 1]

for word in unique:
    print(word)
    wordlist = wordlist.replace(word, str(word.upper()))

print(wordlist)

Вывод должен быть 'Genesis 37:1 Jacob lived in the land of his father's SOJOURNINGS, in the land of Canaan., так как временное пребывание - это первое слово, которое появляется только один раз.Вместо этого он выводит GenesIs 37:1 Jacob lIved In the land of hIs FATher's SOJOURNINGS, In the land of Canaan. Поскольку некоторые другие буквы появляются в ключевых словах, он также пытается использовать их заглавными буквами.

Есть идеи?

Ответы [ 2 ]

1 голос
/ 14 июня 2019

Я довольно значительно переписал код, поскольку некоторые из связанных вызовов replace могут оказаться ненадежными.

import string

# The sentence.
sentence = "Genesis 37:1 Jacob lived in the land of his father's SOJOURNINGS, in the land of Canaan."

rm_punc = sentence.translate(None, string.punctuation)  # remove punctuation
words = rm_punc.split(' ')  # split spaces to get a list of words

# Find all unique word occurrences.
single_occurrences = []
for word in words:
    # if word only occurs 1 time, append it to the list
    if words.count(word) == 1:
        single_occurrences.append(word)

# For each unique word, find it's index and capitalize the letter at that index
# in the initial string (the letter at that index is also the first letter of
# the word). Note that strings are immutable, so we are actually creating a new
# string on each iteration. Also, sometimes small words occur inside of other
# words, e.g. 'an' inside of 'land'. In order to make sure that our call to
# `index()` doesn't find these small words, we keep track of `start` which
# makes sure we only ever search from the end of the previously found word.
start = 0
for word in single_occurrences:
    try:
        word_idx = start + sentence[start:].index(word)
    except ValueError:
        # Could not find word in sentence. Skip it.
        pass
    else:
        # Update counter.
        start = word_idx + len(word)

        # Rebuild sentence with capitalization.
        first_letter = sentence[word_idx].upper()
        sentence = sentence[:word_idx] + first_letter + sentence[word_idx+1:]

print(sentence)
0 голосов
/ 14 июня 2019

Замена текста по шаблонам требует регулярное выражение .

Ваш текст немного хитрый, вам нужно

  • удалить цифры
  • удалить пунктуации
  • разделить на слова
  • забота о капитализации: 'It's' против 'it's'
  • только заменить полный соответствует 'remote' против 'mote' при замене mote
  • и т.д.

Это должно сделать это - см. Комментарии внутри для объяснений:

bible.txt от ваша ссылка

from collections import Counter
from string import punctuation , digits

import re

from collections import defaultdict

with open(r"SO\AllThingsPython\P4\bible.txt") as f:
    s = f.read()

# get a set of unwanted characters and clean the text
ps = set(punctuation + digits)  
s2 = ''.join( c for c in s if c not in ps) 

# split into words
s3 = s2.split()

# create a set of all capitalizations of each word
repl = defaultdict(set)
for word in s3:
    repl[word.upper()].add(word)  # f.e. {..., 'IN': {'In', 'in'}, 'THE': {'The', 'the'}, ...}

# count all words _upper case_ and use those that only occure once
single_occurence_upper_words = [w for w,n in Counter( (w.upper() for w in s3) ).most_common() if n == 1]
text = s

# now the replace part - for all upper single words 
for upp in single_occurence_upper_words:

    # for all occuring capitalizations in the text
    for orig in repl[upp]:

        # use regex replace to find the original word from our repl dict with 
        # space/punktuation before/after it and replace it with the uppercase word
        text = re.sub(f"(?<=[{punctuation} ])({orig})(?=[{punctuation} ])",upp, text)

print(text)

Вывод (укороченный):

Genesis 37:1 Jacob lived in the land of his father's SOJOURNINGS, in the land of Canaan.

2 These are the GENERATIONS of Jacob.

Joseph, being seventeen years old, was pasturing the flock with his brothers. He was a boy with the sons of Bilhah and Zilpah, his father's wives. And Joseph brought a BAD report of them to their father. 3 Now Israel loved Joseph more than any other of his sons, because he was the son of his old age. And he made him a robe of many colors. [a] 4 But when his brothers saw that their father loved him more than all his brothers, they hated him
and could not speak PEACEFULLY to him. 

<snipp>

Регулярное выражение использует синтаксис lookahead '(?=...)' и lookbehind '(?<=...)', чтобы обеспечить замену только полных слов, см. синтаксис регулярного выражения .

...