It seems like every time I want to use string.maketrans and str.translate, I have to stop for a minute and think really hard about how to accomplish what I want to do. Eventually, I wrote this little wrapper class to ease my pain.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | import string
class Translator:
allchars = string.maketrans('','')
def __init__(self, frm='', to='', delete='', keep=None):
if len(to) == 1:
to = to * len(frm)
self.trans = string.maketrans(frm, to)
if keep is None:
self.delete = delete
else:
self.delete = self.allchars.translate(self.allchars, keep.translate(self.allchars, delete))
def __call__(self, s):
return s.translate(self.trans, self.delete)
|
This class handles the three most common cases where I find myself having to stop and think about how to use translate:
1) Keeping only a given set of characters.
>>> trans = Translator(keep=string.digits)
>>> trans('Chris Perkins : 224-7992')
'2247992'
2) Deleting a given set of characters.
>>> trans = Translator(delete=string.digits)
>>> trans('Chris Perkins : 224-7992')
'Chris Perkins : -'
3) Replacing a set of characters with a single character.
>>> trans = Translator(string.digits, '#')
>>> trans('Chris Perkins : 224-7992')
'Chris Perkins : ###-####'
This last one is admittedly a bit of a special case, but it is something I seem to need to do once in a while.
Note that the delete parameter trumps the keep parameter if they overlap:
>>> trans = Translator(delete='abcd', keep='cdef')
>>> trans('abcdef')
'ef'
This is an arbitrary design choice - makes as much sense as anything, I suppose.
See also: 1) http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/101521 for an excellent explanation of maketrans and translate. 2) http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/59857 for an equivalent to Translate(keep=whatever).
Alternate implementation using nested functions. Nice utility!
Here is a drop-in replacement using functions and nested scopes instead of class logic. It is a little bit less wordy and runs a bit faster:
Try a list comprehension.
Your script is helpful.
You might want to assert len(frm) = len(to) before line 8