Преобразование букв в числа и выполнение последовательности операций по длине в Python

Что уже сделано:

  1. Каждая буква строки состоит из фиксированного количества букв, преобразованных в число: например, "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)

Во всяком случае, на том, что я хочу сделать дальше:

  1. В моей последовательности чисел "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
Другие вопросы по тегам