TypeError при использовании replace() из словаря

Прежде всего: пожалуйста, имейте в виду, что я очень новичок в программировании.

Я пытаюсь написать простую программу на Python, которая заменит согласные в строке на согласную + «о» + согласную. Например, «b» будет заменено на «bob», а «d» будет заменено на «dod» (поэтому слово «python» будет заменено на «popytothohonon»).

Для этого я создал словарь, содержащий пары b:bob,c:coc,d:dod и т. д. Затем я использовал команду replace(), чтобы прочитать слово и заменить согласные на их перевод в словаре. Полный фрагмент кода выглядит так:

def replacer(text):
    consonant='bcdfghjklmnpqrstvwxz'
    lexicon={}
    for x in range(0,len(consonant)):
        lexicon[x]=(consonant[x]),(consonant[x]+'o'+consonant[x])
    for i,j in lexicon.items():
        text=(text.replace(i,j))
    return text

Теперь, когда я пытаюсь вызвать эту функцию, я получаю следующую ошибку:

Traceback (most recent call last):
  File "D:\x\x.py", line 37, in <module> 
      print(replacer("python"))
  File "D:\x\x.py", line 17, in replacer 
      text=(text.replace(i,j))
TypeError: Can't convert 'int' object to str implicitly

Но я не использую целые числа! Со словарем должно быть что-то не так, потому что все работает, когда я делаю это "вручную" вот так:

list={'b':'bob', 'c':'coc', 'd':'dod', 'f':'fof', 'g':'gog', 'h':'hoh'......}

Но когда печатаю "нерукотворный" словарь вроде бы все в порядке:

{0: ('b', 'bob'), 1: ('c', 'coc'), 2: ('d', 'dod'), 3: ('f', 'fof')........

Что я делаю не так?


person Moeghoeg    schedule 12.04.2013    source источник


Ответы (4)


lexicon — это словарь с целыми числами в качестве ключей и кортежами в качестве значений. когда вы перебираете его элементы, вы получаете кортежи формы (integer,tuple). Затем вы передаете это целое число и кортеж в text.replace как i и j, поэтому он жалуется. Возможно, вы имели в виду:

 for i,j in lexicon.values():
     ...

Для этой простой замены подойдет str.replace, но для более сложных замен код, вероятно, будет более надежным (и, возможно, выполняться быстрее!), если вы используйте вместо этого re.sub.


Кроме того, как указано в комментариях, в этом случае лучшей структурой данных было бы использование list:

lexicon = [ (x,'{0}o{0}'.format(x)) for x in chars ]

Теперь вы можете построить свой dict из этого списка, если вы действительно хотите:

lexicon = dict(enumerate(lexicon))

но наверное не надо. И в этом случае вы бы перебрали lexicon напрямую:

for i,j in lexicon:
    ...

Если вы собираетесь сделать это только один раз, вы можете даже сделать это лениво, даже не материализуя список, используя выражение генератора:

lexicon = ( (x,'{0}o{0}'.format(x)) for x in chars )
person mgilson    schedule 12.04.2013

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

lexicon = { c: c+'o'+c for c in consonant }

что эквивалентно:

for c in consonant:
  lexicon[c] = c+'o'+c
person RobertT    schedule 12.04.2013

На этот раз словари не нужны, просто перебирайте символы текста, добавляйте гласные или согласные + о + согласные в результирующий массив и присоединяйте его к строке в конце:

def replacer(text):
    consonants = set('bcdfghjklmnpqrstvwxz')
    result = []
    for c in text:
        if c in consonants:
            result.append(c+"o"+c)
        else:
            result.append(c)
    return "".join(result)

print(replacer("python"))


Для опытных пользователей:

def replacer(text):
    return re.sub(r"[bcdfghjklmnpqrstvwxz]", r"\g<0>o\g<0>", text) 


А на ответ "Что я делаю не так?" - словари полезны для произвольных ключей, обычно list.append() предпочтительнее использовать ключи 0-n в словаре. И поскольку вас не интересует позиция согласного, вы можете перебирать строки напрямую следующим образом:

for x in consonant:
    lexicon[x] = x+"o"+x
person Aprillion    schedule 12.04.2013
comment
В этом случае вам лучше сделать consonants set. - person mgilson; 12.04.2013
comment
@мгилсон правда. я просто не видел выражения генератора, такие как set(c for c in "bcdfghjklmnpqrstvwxz"), как очень много для начинающих - person Aprillion; 12.04.2013
comment
set(c for c in "bcdfghjklmnpqrstvwxz")? Почему не set('bcd..'), что кажется вполне понятным? - person DSM; 12.04.2013
comment
@DSM, да, я забыл, что наборы тоже можно создавать из строки, спасибо. - person Aprillion; 12.04.2013

нет... ваши ключи в самодельной версии - строки... ваши кеты в другой версии - целые... целые не имеют метода замены

person Joran Beasley    schedule 12.04.2013
comment
Да, я перепутал ключи и значения. - person Moeghoeg; 12.04.2013