Преобразование букв в числа и выполнение последовательности операций по длине в Python
Что уже сделано:
Каждая буква строки состоит из фиксированного количества букв, преобразованных в число: например, "TAAPAS" теперь равно "122324"
Я был вынужден выполнить это, используя неуклюжий код:
s = s1.replace("A", "2").replace("P", "3").replace("T", "1").replace("S", "4")
потому что, когда я попробовал более стандартный подход на более раннем форуме, код не смог изменить каждую букву:
numerize = {'A':'2', 'P':'3', 'T':'1', 'S':'4'}
for k, v in numerize.iteritems():
string2 = string1.replace(k, v)
Вопрос 1: Есть ли какие-либо предложения о том, почему этот код не работает в моей ситуации? Я даже попробовал следующее, с тем же результатом:
numerize = {'A':'2', 'P':'3', 'T':'1', 'S':'4'}
for k, v in numerize.iteritems():
for i in string1:
string2 = string1.replace(k, v)
Во всяком случае, на том, что я хочу сделать дальше:
В моей последовательности чисел "122324" я хочу выполнить определенный ряд числовых операций, и когда последняя операция будет достигнута, я хочу, чтобы она начиналась сначала... повторяя это столько раз, сколько необходимо для достижения конец моего целого числа.
например, +, *, /
такой, что это выглядит примерно так:
y = 1 + 2 * 2 / 3 + 2 * 4 ...
Q2: это должно быть выполнено в списке номеров? или можно перебрать позиции целого числа, как можно позиции строки. Если нет, то нет ничего страшного в том, чтобы просто разбить мою строку перед ее преобразованием.
Q3. Какой код для выполнения такой задачи? И есть ли название для этого типа процедуры? Использование ключевых слов "recycle" и "math functions" оставляет меня сухим... и кажется, что библиотека itertools не выполняет математику (или, таким образом, на веб-странице нет примеров).
Спасибо!
5 ответов
Все приведенные ответы (@6:30 по Гринвичу) работают только для одной строки.
Если вам нужно закодировать много строк с условием, что для каждой строки вы назначите код 1
до первой буквы в строке, 2
ко второй другой букве во входной строке и т. д. вы можете попробовать следующую функцию.
def numerize(s):
nd = 0
copy = s[::]
for i in range(len(s)):
c = copy[i]
if c.isdigit(): continue
nd = nd + 1
if nd > 9 :
print "Too many different characters in \"%s\"." % s
return None # here you may want to throw
copy = copy.replace(c,repr(nd))
return copy
print numerize('asdeaswes')
Молчаливое предположение, которое я хочу высказать, заключается в том, что входная строка не содержит цифр. Вы можете проверить каждый символ перед обработкой, если вам нужно, например, чтобы единственными допустимыми символами были латинские заглавные буквы от A до Z.
PS: если вам нужен список целых чисел вместо строки цифр,
s/return copy/return [int(d) for d in copy]/
pps: в отношении числовой постобработки, но лучше следовать совету jfs
eval_expr(interlace(numerize("TAAPAS"), cycle("+*/")))
а не изобретать велосипед самостоятельно...
Рекомендуется использовать translate для замены отображения символов, как показано ниже:
from string import maketrans
instr = "APTS"
outstr = "2314"
trans = maketrans(instr, outstr)
print "TAPS".translate(trans)
выход:
1234
Как только у вас будет такой вывод, вы можете выполнять числовые операции, например:
from string import maketrans
instr = "APTS"
outstr = "2314"
trans = maketrans(instr, outstr)
strNumber = "TAPS".translate(trans)
result=0
for n in strNumber:
result = result + int(n) #summing all the digits
print result
выход:
10
>>> eval_expr(interlace(letters2numbers("TAAPAS"), cycle("+*/")))
10.333333333333332
Вопрос 1: Есть ли какие-либо предложения о том, почему этот код не работает в моей ситуации?
Строки неизменны в Python. string1.replace()
не модифицирует string1
, а также string2
перезаписывается на каждой итерации.
Q2: это должно быть выполнено в списке номеров?
Нет. Вы можете создать арифметическое выражение в виде строки без преобразования в int
s, float
сначала.
Q3. Какой код для выполнения такой задачи? И есть ли название для этого типа процедуры?
"TAAPAS"
в"122324"
шаг перевод / кодирование. Шаг перевода, который вы можете выполнить, используя.translate()
Метод, предложенный @user3:import string table = string.maketrans("TAPS", "1234") def letters2numbers(letters): """ >>> letters2numbers("TAAPAS") '122324' """ return letters.translate(table)
"122324"
+cycle("+*/")
в"1 + 2 * 2 / 3 + 2 * 4"
переплетается:def interlace(left, right): """ >>> from itertools import cycle >>> interlace("122324", cycle("+*/")) '1+ 2* 2/ 3+ 2* 4' """ return " ".join(a+b for a, b in zip(left, right))[:-1]
itertools.cycle("+*/")
повторяет последовательность бесконечно много раз, покаzip()
стоп. Он добавляет ненужный оператор в конце, который отрубается с помощью[:-1]
,"1 + 2 * 2 / 3 + 2 * 4"
в10.(3)
Арифметическая оценка:>>> eval_expr('1+ 2* 2/ 3+ 2* 4') 10.333333333333332
где
eval_expr()
это сейфeval()
аналог для простых математических выражений.
Или вы можете объединить все шаги в одну функцию:
from itertools import cycle
from operator import add, sub, mul, floordiv
def eval_letters(letters, operators,
numerize={'A': 2, 'P': 3, 'T': 1, 'S': 4},
functions={'+': add, '-': sub, '*': mul, '/': floordiv}):
"""
>>> eval_letters("TAAPAS", "+*/")
16
"""
numbers = (numerize[c] for c in letters)
operators = cycle(operators) # repeat ad infinitum
result = next(numbers)
for n, op in zip(numbers, operators):
result = functions[op](result, n)
return result
Примечание: здесь я выбрал произвольно floordiv
(3/2==1
) за /
оператор вместо truediv
(3/2==1.5
) использован eval_expr()
,
user3 показал вам, как сделать правильный перевод символов. Одним из ваших вопросов было то, почему ваш код не работал. Просто взгляните на то, что происходит:
>>> string1 = "TAAPAS"
>>> for k, v in numerize.iteritems():
... string2 = string1.replace(k, v)
... print string2
...
TAAPA4
TAA3AS
T22P2S
1AAPAS
В каждой итерации вы перезапускаете ту же строку, поэтому сохраняется только последняя операция замены (строки неизменны, поэтому .replace()
всегда возвращает новую строку вместо изменения той, с которой она работает). Если бы вы использовали string1 = string1.replace(k, v)
, тогда результат был бы верным.
Вы можете использовать нумерацию более простым способом
numerize = {'A':'2', 'P':'3', 'T':'1', 'S':'4'}
string2 = ""
for c in "TAAPAS":
string2 += numerize[c]
print string2