6

I am trying to create a program in python 3.3.3 that will take a string then turn it into numbers (1-26)

I know how to do it for one digit but not 2

translist = str.maketrans("123456789", "ABCDEFGHI")

Is there a way to do this

Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
samrobbins
  • 451
  • 2
  • 6
  • 11

5 Answers5

7

You cannot do what you want with str.translate(); that only works for one-on-one replacements. You are trying to replace one character with two different characters here.

You could use a regular expression instead:

re.sub('[A-Z]', lambda m: str(ord(m.group()) - 64), inputstring)

This takes the ASCII codepoint of each letter and subtracts 64 (A is 65 in the ASCII standard).

Note that this can lead to some confusing ambiguous interpretations:

>>> import re
>>> inputstring = 'FOO BAR BAZ'
>>> re.sub('[A-Z]', lambda m: str(ord(m.group()) - 64), inputstring)
'61515 2118 2126'

Is that 6 1 5 1 5 or 6 15 15 for the first set of numbers? You may want to 0-pad your digits:

re.sub('[A-Z]', lambda m: format(ord(m.group()) - 64, '02d'), inputstring)

which produces:

>>> re.sub('[A-Z]', lambda m: format(ord(m.group()) - 64, '02d'), inputstring)
'061515 020118 020126'
Martijn Pieters
  • 1,048,767
  • 296
  • 4,058
  • 3,343
  • I tried putting the second section of code through the shell and it said "SyntaxError: multiple statements found while compiling a single statement" How could I fix this? – samrobbins Aug 08 '14 at 11:12
  • @Sam: that sounds as if Python found additional information on a line of code; make sure your `()` parentheses are correctly balanced. – Martijn Pieters Aug 08 '14 at 11:17
  • I found an answer that worked somewhere else but thanks for the help. – samrobbins Aug 08 '14 at 11:22
  • [This](http://stackoverflow.com/questions/8452961/convert-string-to-ascii-value-python) – samrobbins Aug 08 '14 at 11:26
  • @Sam: note that the answers there assume that you wanted to replace **all** characters in the string (not just letters). – Martijn Pieters Aug 08 '14 at 11:26
3

By no mean am I the best Python programmer (still beginning my journey), however this code seems to do what you want.

Firstly, make a dictionary like so:

abc = {"A": "1",
   "B": "2",
   "C": "3",
   "D": "4",
   "E": "5",
   "F": "6",
   "G": "7",
   "H": "8",
   "I": "9",
   "J": "10",
   "K": "11",
   "L": "12",
   "M": "13",
   "N": "14",
   "O": "15", 
   "P": "16",
   "Q": "17",
   "R": "18",
   "S": "19",
   "T": "20",
   "U": "21",
   "V": "22",
   "W": "23",
   "X": "24",
   "Y": "25",
   "Z": "26"}

Then you could do so:

txt = str(input("Text: ")).upper()
ntxt = ""

for char in txt:
    if char in abc:
        ntxt += abc[char]
    else:
        ntxt += char

print("New string:", ntxt)
1

I had this same problem to solve and was able to solve it with a oneliner:

def replace(s, r):
    return ''.join([r.get(x, x) for x in s])

This function takes the string to be iterated over and a dictionary of replacements, with the keys being the chars to find and the values being the replacement char(s). The comprehension iterates through the chars of the string, if the char is a key in the dictionary of replacements it'll use that value, otherwise it just returns the char. Then we collect it back into a string with the join function.

My use case of this was to write a simple url percent-encoder:

def url_encode(s):
    r = {
            "!":"%21",
            "#":"%23",
            "$":"%24",
            "%":"%25",
            "&":"%26",
            "'":"%27",
            "(":"%28",
            ")":"%29",
            "*":"%2A",
            "+":"%2B",
            ",":"%2C",
            "/":"%2F",
            ":":"%3A",
            ";":"%3B",
            "=":"%3D",
            "?":"%3F",
            "@":"%40",
            "[":"%5B",
            "]":"%5D",
        }
    return replace(s, r)

def replace(s, r):
    return ''.join([r.get(x, x) for x in s])

Ian Pringle
  • 323
  • 1
  • 5
  • 19
0

You can use a list comprehension, format and map:

>>> s='ABCXYZ'
>>> [format(oc, '02d') for oc in map(ord, s)]
['65', '66', '67', '88', '89', '90']

Then rejoin that into a single string if you wish:

>>> ''.join([format(oc, '02d') for oc in map(ord, s)])
'656667888990'
dawg
  • 98,345
  • 23
  • 131
  • 206
0

Recent I had same issues like Sam's. So I googled some keywords and fount my solutions.

http://code.activestate.com/recipes/81330-single-pass-multiple-replace/

Btw, this method maybe a little bit slower, but useful for my cases.

Hope it would be helpful to you, and sorry for my bad English.

staticor
  • 620
  • 9
  • 19