append special chars with "\"

Bengt Richter bokr at oz.net
Tue Sep 30 23:45:52 EDT 2003


On Tue, 30 Sep 2003 10:36:48 +0200, Tertius <tcronj at ananzi.co.za> wrote:

>Alex Martelli wrote:
>> tertius wrote:
>> 
>> 
>>>Is there a better way to append certain chars in a string with a
>>>backslash that the example below?
>>>
>>>chr = "#$%^&_{}"          # special chars to look out for
<nit1 kind="builtin-shadowing-abuse"/>
>>>str = "123 45^ & 00 0_"   # string to convert
<nit2 kind="builtin-shadowing-abuse"/>
>>>n = ""                    # init new string
>>>for i in str:
>>>     if i in chr:          # if special character in str
>>>         n+='\\'           # append it with a backslash
>>>     n+=i
[Note that n+=i comes _after_ n+='\\' -- cf nit3]

>>>print "old:",str
>>>print "new:",n
>> 
>> 
>> If you can afford some a priori preparation, make a dictionary
>> once and for all that maps each character (that isn't to be
>> represented by itself) to the string that represents it.  E.g.,
>> if you inevitably start with a chr string as above, you can
>> make the dictionary as follows:
>> 
>> charmap = {}
>> for c in chr: charmap[c] = c+'\\'
<nit 3>
   for c in chr: charmap[c] = '\\'+c
</nit3>
>> 
>> You can also write out the dict literal directly, and in
>> any case you only need to prepare this charmap once and
>> can then use it to prepare any number of translations.
>> 
>> Once you have this charmap, you can use its get method to
>> get the translations -- and prepare a *LIST OF STRINGS* to
>> be joined up at the end, that's MUCH, *MUCH* faster than
>> a loop using += on a string:
>> 
>> pieces = [charmap.get(c,c) for c in str]
>> 
>> and finally:
>> 
>> n = ''.join(pieces)
>> 
>> 
>> Alex
>> 
>
>*MUCH* nicer :)
>Thanks!

Re nits: Alex must have been doing this while talking on the 'phone and playing bridge
or I think he would have mentioned that using builtin names (e.g., chr & str) for your
variables is a bad idea. I think your comment "append _it_ with a backslash" was misleading,
since the "it" was not the character, but the accumulating output.

If you want to play, you can also define a translation function like the following ;-)

 >>> trans = (lambda f,s: ''.join(map(f,s))).__get__(
 ...             (lambda d,c: d.get(c,c)).__get__(
 ...                 dict([(c,'\\'+c) for c in '#$%^&_{}'])))
 >>> print trans("123 45^ & 00 0_")
 123 45\^ \& 00 0\_
 >>> trans
 <bound method ?.<lambda> of <bound method ?.<lambda> of {'#': '\\#', '%': '\\%', '$': '\\$', '&'
 : '\\&', '{': '\\{', '}': '\\}', '_': '\\_', '^': '\\^'}>>

(I think all the work is done up front ;-)

This form is obviously easy to parameterize as to which characters you want escaped, BTW:

 >>> def maketrans(escaped='#$%^&_{}'):
 ...     return (lambda f,s: ''.join(map(f,s))).__get__(
 ...                 (lambda d,c: d.get(c,c)).__get__(
 ...                     dict([(c,'\\'+c) for c in escaped])))
 ...
 >>> trans = maketrans()
 >>> print trans("123 45^ & 00 0_")
 123 45\^ \& 00 0\_
 >>> trans = maketrans('135&')
 >>> print trans("123 45^ & 00 0_")
 \12\3 4\5^ \& 00 0_

Now Alex can <nit> me back ;-)

Regards,
Bengt Richter




More information about the Python-list mailing list