Nested string substitutions
holger krekel
pyth at devel.trillke.net
Sat Dec 21 07:30:57 EST 2002
Lulu of the Lotus-Eaters wrote:
> |def expand(d):
> | while filter(lambda (n, v): d.__setitem__(n,
> | reduce(lambda x,k: x.replace(k, d[k]), d, v)
> | ) or v!=d[n], d.items()): pass
>
> Wow! Who ever said Perl was hard to read :-). How long did that take
> to think of, Holger?
I produced a *readable* versions in 1-2 hours. Using all the ideas
from these versions the above snippet took around 20 minutes. Maybe
i mistake your original mail (where you mentioned one or two lines).
FWIW, if i wanted readability and general usability i'd go for
making subst_dict a callable object providing substition for
a string. And provide a separate (in place) expand method.
class subst_dict(dict):
def __init__(self, *args, **kwargs):
"""convenience: keyword arguments go into dict """
super(subst_dict, self).__init__(*args)
self.update(kwargs)
def __call__(self, string, key=None):
"""replace occurences of 'key' in 'string' with dict-value.
for a None key all keys of the dict are applied
sequentially. If a key is not in the dict the
string is returned unmodified.
"""
if key is None:
return reduce(self, self, string)
newstring = string.replace(key, self.get(key,key))
if newstring != string:
return self(newstring)
return newstring
def expand(self):
"""expand all dictionary keys in place. """
for key,value in self.items():
self[key] = self(value)
usage:
>>> d = subst_dict(a='1', b='2', c='ab')
>>> d('c') # doesn't change dict
'12'
>>> d['12']='77'
>>> d('c')
'77'
>>> d
{'a': '1', '12': '77', 'c': 'ab', 'b': '2'}
>>> d.expand()
>>> d
{'a': '1', '12': '77', 'c': '77', 'b': '2'}
>>>
This way you can also pass a subst_dict instance around
and do stuff like
subst_strings = map(d, strings)
expand() merely becomes an optimization.
cheers,
holger
More information about the Python-list
mailing list