Подтвердить что ты не робот

Функция замены Python [заменить один раз]

Мне нужна помощь с программой, которую я создаю на Python.

Предположим, я хотел заменить каждый экземпляр слова "steak" на "ghost" (просто пойти с ним...), но я также хотел заменить каждый экземпляр слова "ghost" на "steak" тем же время. Следующий код не работает:

 s="The scary ghost ordered an expensive steak"
 print s
 s=s.replace("steak","ghost")
 s=s.replace("ghost","steak")
 print s

он печатает: The scary steak ordered an expensive steak

То, что я пытаюсь получить, это The scary steak ordered an expensive ghost

4b9b3361

Ответ 1

Я бы, вероятно, использовал regex здесь:

>>> import re
>>> s = "The scary ghost ordered an expensive steak"
>>> sub_dict = {'ghost':'steak','steak':'ghost'}
>>> regex = '|'.join(sub_dict)
>>> re.sub(regex, lambda m: sub_dict[m.group()], s)
'The scary steak ordered an expensive ghost'

Или, как функцию, которую вы можете скопировать/вставить:

import re
def word_replace(replace_dict,s):
    regex = '|'.join(replace_dict)
    return re.sub(regex, lambda m: replace_dict[m.group()], s)

В принципе, я создаю сопоставление слов, которые я хочу заменить другими словами (sub_dict). Я могу создать регулярное выражение из этого сопоставления. В этом случае регулярное выражение "steak|ghost" (или "ghost|steak" - порядок не имеет значения), а механизм регулярных выражений выполняет остальную часть работы по поиску неперекрывающихся последовательностей и соответственно заменяет их.


Некоторые, возможно, полезные модификации

  • regex = '|'.join(map(re.escape,replace_dict)) - Позволяет регулярным выражениям иметь в них специальный синтаксис регулярных выражений (например, скобки). Это ускользает от специальных символов, чтобы регулярные выражения соответствовали литералу.
  • regex = '|'.join(r'\b{0}\b'.format(x) for x in replace_dict) - убедитесь, что мы не сопоставимы, если одно из наших слов является подстрокой в ​​другом слове. Другими словами, измените he на she, но не the на tshe.

Ответ 2

Разделите строку на одну из целей, замените ее и соедините все вместе.

pieces = s.split('steak')
s = 'ghost'.join(piece.replace('ghost', 'steak') for piece in pieces)

Это работает точно так же, как .replace(), включая игнорирование границ слов. Поэтому он превратит "steak ghosts" в "ghost steaks".

Ответ 3

Переименуйте одно из слов в значение temp, которое не встречается в тексте. Обратите внимание, что это не самый эффективный способ для очень большого текста. Для этого a re.sub может быть более подходящим.

 s="The scary ghost ordered an expensive steak"
 print s
 s=s.replace("steak","temp")
 s=s.replace("ghost","steak")
 S=s.replace("temp","steak")
 print s

Ответ 4

Используйте переменную count в методе string.replace(). Поэтому, используя свой код, вы wouold имеете:

s="The scary ghost ordered an expensive steak"
print s
s=s.replace("steak","ghost", 1)
s=s.replace("ghost","steak", 1)
print s

http://docs.python.org/2/library/stdtypes.html

Ответ 5

Как насчет чего-то подобного? Сохраните оригинал в разделенном списке, затем введите перевод dict. Сохраняет ваш основной код коротким, а затем просто отрегулируйте dict, когда вам нужно настроить перевод. Кроме того, легко переносить на функцию:

 def translate_line(s, translation_dict):
    line = []
    for i in s.split():
       # To take account for punctuation, strip all non-alnum from the
       # word before looking up the translation.
       i = ''.join(ch for ch in i if ch.isalnum()]
       line.append(translation_dict.get(i, i))
    return ' '.join(line)


 >>> translate_line("The scary ghost ordered an expensive steak", {'steak': 'ghost', 'ghost': 'steak'})
 'The scary steak ordered an expensive ghost'

Ответ 6

Примечание. Учитывая мнение этого Вопроса, я восстановил и переписал его для различных типов тестовых случаев.

Я рассмотрел четыре конкурирующие реализации из ответов

>>> def sub_noregex(hay):
    """
    The Join and replace routine which outpeforms the regex implementation. This
    version uses generator expression
    """
    return 'steak'.join(e.replace('steak','ghost') for e in hay.split('ghost'))

>>> def sub_regex(hay):
    """
    This is a straight forward regex implementation as suggested by @mgilson
    Note, so that the overheads doesn't add to the cummulative sum, I have placed
    the regex creation routine outside the function
    """
    return re.sub(regex,lambda m:sub_dict[m.group()],hay)

>>> def sub_temp(hay, _uuid = str(uuid4())):
    """
    Similar to Mark Tolonen implementation but rather used uuid for the temporary string
    value to reduce collission
    """
    hay = hay.replace("steak",_uuid).replace("ghost","steak").replace(_uuid,"steak")
    return hay

>>> def sub_noregex_LC(hay):
    """
    The Join and replace routine which outpeforms the regex implementation. This
    version uses List Comprehension
    """
    return 'steak'.join([e.replace('steak','ghost') for e in hay.split('ghost')])

Обобщенная функция времени-времени

>>> def compare(n, hay):
    foo = {"sub_regex": "re",
           "sub_noregex":"",
           "sub_noregex_LC":"",
           "sub_temp":"",
           }
    stmt = "{}(hay)"
    setup = "from __main__ import hay,"
    for k, v in foo.items():
        t = Timer(stmt = stmt.format(k), setup = setup+ ','.join([k, v] if v else [k]))
        yield t.timeit(n)

И обобщенная тестовая процедура

>>> def test(*args, **kwargs):
    n = kwargs['repeat']
    print "{:50}{:^15}{:^15}{:^15}{:^15}".format("Test Case", "sub_temp",
                             "sub_noregex ", "sub_regex",
                             "sub_noregex_LC ")
    for hay in args:
        hay, hay_str = hay
        print "{:50}{:15.10}{:15.10}{:15.10}{:15.10}".format(hay_str, *compare(n, hay))

И результаты теста следующие

>>> test((' '.join(['steak', 'ghost']*1000), "Multiple repeatation of search key"),
         ('garbage '*998 + 'steak ghost', "Single repeatation of search key at the end"),
         ('steak ' + 'garbage '*998 + 'ghost', "Single repeatation of at either end"),
         ("The scary ghost ordered an expensive steak", "Single repeatation for smaller string"),
         repeat = 100000)
Test Case                                            sub_temp     sub_noregex      sub_regex   sub_noregex_LC 
Multiple repeatation of search key                   0.2022748797   0.3517142003   0.4518992298   0.1812594258
Single repeatation of search key at the end          0.2026047957   0.3508259952   0.4399926194   0.1915298898
Single repeatation of at either end                  0.1877455356   0.3561734007   0.4228843986   0.2164233388
Single repeatation for smaller string                0.2061019057   0.3145984487   0.4252060592   0.1989413449
>>> 

Основываясь на результатах теста

  • Non Regex LC и подстановка переменных temp имеют лучшую производительность, хотя производительность использования временной переменной непротиворечива.

  • Версия LC имеет лучшую производительность по сравнению с генератором (подтверждено)

  • Regex более чем в два раза медленнее (поэтому, если фрагмент кода является узким местом, тогда изменение реализации может быть пересмотрено)

  • Версия Regex и non regex эквивалентна Robust и может масштабировать