def translate(s, a, b=None, c=None): """Return ``s`` where characters have been replaced or deleted. SYNTAX ====== translate(s, None, deletechars): all characters in ``deletechars`` are deleted translate(s, map [,deletechars]): all characters in ``deletechars`` (if provided) are deleted then the replacements defined by map are made; if the keys of map are strings then the longer ones are handled first. Multicharacter deletions should have a value of ''. translate(s, oldchars, newchars, deletechars) all characters in ``deletechars`` are deleted then each character in ``oldchars`` is replaced with the corresponding character in ``newchars`` Examples ======== >>> from sympy.utilities.misc import translate >>> from sympy.core.compatibility import unichr >>> abc = 'abc' >>> translate(abc, None, 'a') 'bc' >>> translate(abc, {'a': 'x'}, 'c') 'xb' >>> translate(abc, {'abc': 'x', 'a': 'y'}) 'x' >>> translate('abcd', 'ac', 'AC', 'd') 'AbC' There is no guarantee that a unique answer will be obtained if keys in a mapping overlap are the same length and have some identical sequences at the beginning/end: >>> translate(abc, {'ab': 'x', 'bc': 'y'}) in ('xc', 'ay') True """ from sympy.core.compatibility import maketrans, PY3 mr = {} if a is None: assert c is None if not b: return s c = b a = b = '' else: if type(a) is dict: short = {} for k in list(a.keys()): if len(k) == 1 and len(a[k]) == 1: short[k] = a.pop(k) mr = a c = b if short: a, b = [''.join(i) for i in list(zip(*short.items()))] else: a = b = '' else: assert len(a) == len(b) if PY3: if c: s = s.translate(maketrans('', '', c)) s = replace(s, mr) return s.translate(maketrans(a, b)) else: # when support for Python 2 is dropped, this if-else-block # can be replaced with the if-clause if c: c = list(c) rem = {} for i in range(-1, -1 - len(c), -1): if ord(c[i]) > 255: rem[c[i]] = '' c.pop(i) s = s.translate(None, ''.join(c)) s = replace(s, rem) if a: a = list(a) b = list(b) for i in range(-1, -1 - len(a), -1): if ord(a[i]) > 255 or ord(b[i]) > 255: mr[a.pop(i)] = b.pop(i) a = ''.join(a) b = ''.join(b) s = replace(s, mr) table = maketrans(a, b) # s may have become unicode which uses the py3 syntax for translate if type(table) is str and type(s) is str: s = s.translate(table) else: s = s.translate(dict( [(i, ord(c)) for i, c in enumerate(table)])) return s
def translate(s, a, b=None, c=None): """Return ``s`` where characters have been replaced or deleted. SYNTAX ====== translate(s, None, deletechars): all characters in ``deletechars`` are deleted translate(s, map [,deletechars]): all characters in ``deletechars`` (if provided) are deleted then the replacements defined by map are made; if the keys of map are strings then the longer ones are handled first. Multicharacter deletions should have a value of ''. translate(s, oldchars, newchars, deletechars) all characters in ``deletechars`` are deleted then each character in ``oldchars`` is replaced with the corresponding character in ``newchars`` Examples ======== >>> from sympy.utilities.misc import translate >>> from sympy.core.compatibility import unichr >>> abc = 'abc' >>> translate(abc, None, 'a') 'bc' >>> translate(abc, {'a': 'x'}, 'c') 'xb' >>> translate(abc, {'abc': 'x', 'a': 'y'}) 'x' >>> translate('abcd', 'ac', 'AC', 'd') 'AbC' There is no guarantee that a unique answer will be obtained if keys in a mapping overlap are the same length and have some identical sequences at the beginning/end: >>> translate(abc, {'ab': 'x', 'bc': 'y'}) in ('xc', 'ay') True """ from sympy.core.compatibility import maketrans, PY3 mr = {} if a is None: if c is not None: raise ValueError( 'c should be None when a=None is passed, instead got %s' % c) if b is None: return s c = b a = b = '' else: if type(a) is dict: short = {} for k in list(a.keys()): if len(k) == 1 and len(a[k]) == 1: short[k] = a.pop(k) mr = a c = b if short: a, b = [''.join(i) for i in list(zip(*short.items()))] else: a = b = '' elif len(a) != len(b): raise ValueError('oldchars and newchars have different lengths') if PY3: if c: s = s.translate(maketrans('', '', c)) s = replace(s, mr) return s.translate(maketrans(a, b)) else: # when support for Python 2 is dropped, this if-else-block # can be replaced with the if-clause if c: c = list(c) rem = {} for i in range(-1, -1 - len(c), -1): if ord(c[i]) > 255: rem[c[i]] = '' c.pop(i) s = s.translate(None, ''.join(c)) s = replace(s, rem) if a: a = list(a) b = list(b) for i in range(-1, -1 - len(a), -1): if ord(a[i]) > 255 or ord(b[i]) > 255: mr[a.pop(i)] = b.pop(i) a = ''.join(a) b = ''.join(b) s = replace(s, mr) table = maketrans(a, b) # s may have become unicode which uses the py3 syntax for translate if isinstance(table, str) and isinstance(s, str): s = s.translate(table) else: s = s.translate(dict([(i, ord(c)) for i, c in enumerate(table)])) return s