6

I want to replace letters in a character vector by other ones, using a dictionary created with dict, as follows

import string

trans1 = str.maketrans("abc","cda")
trans = dict(zip("abc","cda"))
out1 = "abcabc".translate(trans1)
out = "abcabc".translate(trans)

print(out1)
print(out)

The desired output is "cdacda"

What I get is

cdacda
abcabc

Now out1 is this desired output, but out is not. I can not figure out why this is the case. How can I use the dictionary created via dict in the translate function? So what do I have to change if I want to use translate with trans?

user3825755
  • 883
  • 2
  • 10
  • 29
  • Can you show us your output when running the code. Is there any exception? I'm asking becouse your code, how it is shown above, doesn't run properly. – Magnun Leno Apr 07 '16 at 20:50
  • 1
    I think you meant to do `string.maketrans("abc","cda")`, which definitely does not return the same thing as `dict(zip("abc","cda"))` – OneCricketeer Apr 07 '16 at 20:50
  • @MagnunLeno I added the output – user3825755 Apr 07 '16 at 20:52
  • The problem is the dict dont do the correct translation: the characters are not converted to their ASCII codes. – Walter_Ritzel Apr 07 '16 at 20:53
  • @cricket_007 yes, the output is different (see edited post), but I would like to know how I can achieve the same using the dict version. So how can I get `out` to be the same as `out1` – user3825755 Apr 07 '16 at 20:54
  • @Walter_Ritzel So how can I do something similar using dict? It seems that this should be a standard usage of dict. – user3825755 Apr 07 '16 at 20:54
  • Print your two trans values, you will see a big difference – OneCricketeer Apr 07 '16 at 20:56
  • @cricket_007 yes, I am aware of the difference. Which is why I am wondering what I have to change in the application of the translate function to get the same output – user3825755 Apr 07 '16 at 21:02
  • This function is different in Python 2 and Python 3, please mention which version you use when asking a question. Python 2 doesn't accept a dict, but **Python 3 does**. However, in v3 the key must be the ord() of the character to replace and not the character itself. – RedGlyph Sep 04 '19 at 17:20

3 Answers3

14

str.translate supports dicts perfectly well (in fact, it supports anything that supports indexing, i.e. __getitem__) – it's just that the key has to be the ordinal representation of the character, not the character itself.

Compare:

>>> "abc".translate({"a": "d"})
'abc'
>>> "abc".translate({ord("a"): "d"})
'dbc'
ash
  • 5,139
  • 2
  • 27
  • 39
2

I do not think the method translate will accept a dictionary object. Aditionlly, you should look at what you are creating:

>>> dict(zip("abc","cda"))
{'c': 'a', 'a': 'c', 'b': 'd'}

I do not think that is what you wanted. zip pairs off correspondingly indexed elements from the first and second argument.

You could write a work around:

def translate_from_dict(original_text,dictionary_of_translations):
    out = original_text
    for target in dictionary_of_translations:
        trans = str.maketrans(target,dictionary_of_translations[target])
        out = out.translate(trans)
    return out

trans = {"abc":"cda"}
out = translate_from_dict("abcabc",trans)
print(out)

Usage of the dict function to create the dictionary. Read the function definition.

>>> dict([("abc","cda")])
{"abc":"cda"}
Farmer Joe
  • 6,020
  • 1
  • 30
  • 40
  • I get an error message: TypeError: translate() takes exactly one argument (2 given) – user3825755 Apr 07 '16 at 20:57
  • @user3825755 I wrote it off the cuff. My last edit should run fine. – Farmer Joe Apr 07 '16 at 21:04
  • With your edit, it works as it should, however, it no longer uses the `dict` function. I was wondering how I can use the dict function in this context to achieve the same output – user3825755 Apr 07 '16 at 21:05
  • @user3825755 `dict` is just a function which creates a dictionary, I made an edit describing it. – Farmer Joe Apr 07 '16 at 21:08
  • So if I set `trans2 = dict([("abc","cda")])`, shouln't then `out2 = "abcabc".translate(trans2)` work? But I get "abcabc" back – user3825755 Apr 07 '16 at 21:12
  • @user3825755 You **cannot** pass a dictionary to the [`translate`](https://docs.python.org/2/library/string.html#string.translate) function. The adjustment to the way you were using the `dict` function does not change that. `translate(..)` accepts a `table` object which is created by the [`maketrans`](https://docs.python.org/2/library/string.html#string.maketrans) method. If you want to use a dictionary to feed a serious of translations to the method `translate` you will have to use a strategy similar to the one I described in my answer. – Farmer Joe Apr 07 '16 at 22:05
  • @user3825755 Methods in python (and most programming languages) generally accept a certain type of data as an argument. The `translate` method asks for a `table` type of object. It knows what to do with a `table`. Think of it as a mathematical function. If I told you `f(x) = x + 1`, and then the I asked what `f(2)` equals you could tell me because you know how to add 1 to 2. If I gave you a couch and said what is `f(couch)` you would look at me funny. The `translate` method is expecting a `table`, so it does not behave as expected when given a `dictionary`. – Farmer Joe Apr 07 '16 at 22:34
  • 1
    Yes, I realize that now. It just seemed to me that using translate in the naive way I did should be a natural application of such dict objects. Thanks for your help – user3825755 Apr 08 '16 at 09:26
0

The string.translate doesn't support dictionaries as arguments:

translate(s, table, deletions='')
    translate(s,table [,deletions]) -> string

    Return a copy of the string s, where all characters occurring
    in the optional argument deletions are removed, and the
    remaining characters have been mapped through the given
    translation table, which must be a string of length 256.  The
    deletions argument is not allowed for Unicode strings.

So, you have to write your own function.

Also, revise your code as it wont run in any python version that I know. It has at least 2 exceptions.

cs95
  • 379,657
  • 97
  • 704
  • 746
Magnun Leno
  • 2,728
  • 20
  • 29
  • sorry, I am a total python newbie. I use Python 3.5 with Spyder, where the code as I have written it runs fine – user3825755 Apr 07 '16 at 21:03
  • @user3825755 which python version are you using? For me there is an exception in line 3 (str.maketrans("abc","cda")), since str doesn't have the maketrans method, line 6 (out = "abcabc".translate(trans)), invalid argument, and line 9 (print(out)), inexistent variable out. – Magnun Leno Apr 08 '16 at 12:46
  • I think Python 3.5. Yesterday there was a (new deleted) comment by someone who said it worked fine with Python 3.5.1 – user3825755 Apr 08 '16 at 13:15
  • @user3825755 I'm running Python 3.4.1. I'll check this code in my laptop later, which has Python 3.5. Thanks... – Magnun Leno Apr 08 '16 at 13:22