Вход:
string = "My dear adventurer, do you understand the nature of the given discussion?"
ожидаемый результат:
string = 'My dear ##########, do you ########## the nature ## the given ##########?'
Как можно заменить третье слово в строке слов эквивалентом длины # этого слова, избегая при этом подсчета специальных символов, встречающихся в строке, таких как апострофы ('), кавычки ("), точки (.), запятые (, ), восклицательные знаки (!), вопросительные знаки (?), двоеточия (:) и точки с запятой (;).
Я воспользовался подходом преобразования строки в список элементов, но мне трудно отфильтровать специальные символы и заменить слова эквивалентом #. Есть ли лучший способ сделать это?
С помощью некоторого регулярного выражения. Пояснение в комментариях.
import re
imp = "My dear adventurer, do you understand the nature of the given discussion?"
every_nth = 3 # in case you want to change this later
out_list = []
# split the input at spaces, enumerate the parts for looping
for idx, word in enumerate(imp.split(' ')):
# only do the special logic for multiples of n (0-indexed, thus +1)
if (idx + 1) % every_nth == 0:
# find how many special chars there are in the current segment
len_special_chars = len(re.findall(r'[.,!?:;\'"]', word))
# ^ add more special chars here if needed
# subtract the number of special chars from the length of segment
str_len = len(word) - len_special_chars
# repeat '#' for every non-special char and add the special chars
out_list.append('#'*str_len + word[-len_special_chars] if len_special_chars > 0 else '')
else:
# if the index is not a multiple of n, just add the word
out_list.append(word)
print(' '.join(out_list))
Это был мой первый подход, но, в конце концов, риск наличия символов, которые не считаются специальными символами, меньше, чем я это сделал. Например, «é» и тому подобное.
Тогда out_list.append(re.sub('[^.,!?:;\\\'"]', "#", word))
должно работать
Для ввода: строка = "Мой дорогой авантюрист, ты понимаешь суть данного обсуждения?"
Что за ошибка?
Вывод такой: Уважаемый ##########, вы ###########у природы ##о данной ##########?
Небольшая ошибка обнаружена во втором и третьем словах, а также в том, что буквы u и o не заштрихованы. Просмотрите код, чтобы увидеть, есть ли какие-либо изменения, которые можно внести.
Попробуйте заменить все под if на out_list.append(re.sub('[^.,!?:;\\\'"]', "#", word))
@white Есть проблема с вашим кодом. Часть + word[-len_special_chars]
добавит первую букву исходного слова, если оно не содержит специального символа. Вам понадобится еще один if
для этого
Я внес небольшое изменение в код, и он работает нормально: # повторите '#' для каждого неспециального символа и добавьте специальные символы redacted_sentence.append('#'*str_len )
Извини за это. Почему-то я этого не заметил, когда тестировал свой код. Я изменил строку на: out_list.append('#'*str_len + word[-len_special_chars] if len_special_chars > 0 else '')
Да, это часть, которую я изменил, она работает нормально, если вы не добавляете раздел кода + word[-len_special_chars]. Все еще нужно немного настроить его, но это, безусловно, лучшее решение проблемы. Спасибо!!
@white тщательно проверит код и обновит ветку, как только я устраню любые ошибки, которые могут появиться. Спасибо!!
Есть более эффективные способы решения этого вопроса, но я надеюсь, что этот самый простой!
Мой подход:
- Split the sentence into a list of the words
- Using that, make a list of every third word.
- Remove unwanted characters from this
- Replace third words in original string with # times the length of the word.
Вот код (объяснение в комментариях):
# original line
line = "My dear adventurer, do you understand the nature of the given discussion?"
# printing original line
print(f'\n\nOriginal Line:\n"{line}"\n')
# printing somehting to indicate that next few prints will be for showing what is happenning after each lone
print('\n\nStages of parsing:')
# splitting by spaces, into list
wordList = line.split(' ')
# printing wordlist
print(wordList)
# making list of every third word
thirdWordList = [wordList[i-1] for i in range(1,len(wordList)+1) if i%3==0]
# pritning third-word list
print(thirdWordList)
# characters that you don't want hashed
unwantedCharacters = ['.','/','|','?','!','_','"',',','-','@','\n','\\',':',';','(',')','<','>','{','}','[',']','%','*','&','+']
# replacing these characters by empty strings in the list of third-words
for unwantedchar in unwantedCharacters:
for i in range(0,len(thirdWordList)):
thirdWordList[i] = thirdWordList[i].replace(unwantedchar,'')
# printing third word list, now without punctuation
print(thirdWordList)
# replacing with #
for word in thirdWordList:
line = line.replace(word,len(word)*'#')
# Voila! Printing the result:
print(f'\n\nFinal Output:\n"{line}"\n\n')
Надеюсь это поможет!
Это очень нестабильно, всякий раз, когда слово появляется дважды, и одно из них является третьим, оба будут заменены, например. в line = "My dear adventurer, do you understand the nature of the given discussion discussion?"
@FlyingTeller А, я только что понял. Если повторяется третье слово, оба будут хешированы. Я думаю, что это делает мой ответ недействительным. Как я могу это исправить?
Следующие работы и не используют регулярные выражения
special_chars = {'.','/','|','?','!','_','"',',','-','@','\n','\\'}
def format_word(w, fill):
if w[-1] in special_chars:
return fill*(len(w) - 1) + w[-1]
else:
return fill*len(w)
def obscure(string, every=3, fill='#'):
return ' '.join(
(format_word(w, fill) if (i+1) % every == 0 else w)
for (i, w) in enumerate(string.split())
)
Вот несколько примеров использования
In [15]: obscure(string)
Out[15]: 'My dear ##########, do you ########## the nature ## the given ##########?'
In [16]: obscure(string, 4)
Out[16]: 'My dear adventurer, ## you understand the ###### of the given ##########?'
In [17]: obscure(string, 3, '?')
Out[17]: 'My dear ??????????, do you ?????????? the nature ?? the given ???????????'
Я решил это с помощью:
s = "My dear adventurer, do you understand the nature of the given discussion?"
def replace_alphabet_with_char(word: str, replacement: str) -> str:
new_word = []
alphabet = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'
for c in word:
if c in alphabet:
new_word.append(replacement)
else:
new_word.append(c)
return "".join(new_word)
every_nth_word = 3
s_split = s.split(' ')
result = " ".join([replace_alphabet_with_char(s_split[i], '#') if i % every_nth_word == every_nth_word - 1 else s_split[i] for i in range(len(s_split))])
print(result)
Выход:
My dear ##########, do you ########## the nature ## the given ##########?
Смесь регулярных выражений и манипуляций со строками
import re
string = "My dear adventurer, do you understand the nature of the given discussion?"
new_string = []
for i, s in enumerate(string.split()):
if (i+1) % 3 == 0:
s = re.sub(r'[^\.:,;\'"!\?]', '#', s)
new_string.append(s)
new_string = ' '.join(new_string)
print(new_string)
Также отлично работает и с очень эффективным кодом!
Вы также можете просто сделать
out_list.append(re.sub(r"[A-Za-z]", "#", word))