Python translate with multiple characters
Asked Answered
C

5

7

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

Chymotrypsin answered 8/8, 2014 at 11:2 Comment(0)
A
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'
Anurous answered 8/8, 2014 at 11:5 Comment(6)
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?Chymotrypsin
@Sam: that sounds as if Python found additional information on a line of code; make sure your () parentheses are correctly balanced.Anurous
I found an answer that worked somewhere else but thanks for the help.Chymotrypsin
ThisChymotrypsin
@Sam: note that the answers there assume that you wanted to replace all characters in the string (not just letters).Anurous
You can do what you want with str.translate(); that works for one-to-many replacments!Indifferent
C
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)
Corky answered 1/10, 2018 at 15:6 Comment(0)
M
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])

Maleeny answered 21/10, 2021 at 17:11 Comment(0)
W
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'
Wofford answered 8/8, 2014 at 18:8 Comment(0)
I
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.

Intaglio answered 9/4, 2015 at 7:54 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.