Nested string substitutions

holger krekel pyth at devel.trillke.net
Fri Dec 20 07:16:17 EST 2002


Lulu of the Lotus-Eaters wrote:
> I think I am being daft here.  But I cannot think of an elegant way to
> perform a nested expansion of a set of substitution patterns.

Originally i wanted to finish some client work but got distracted
by your mail :-)

> For example, let's say I have a dictionary of patterns:
> 
>     subs = {'foo':'bar baz',
>             'bar':'bat bam ber',
>             'baz':'zat zam zer',
>             'bam':'yat yam yer',
>             'yam':'spam and eggs'}
> 
> I want to "fully expand" the substitution dictionary, getting:
> 
>     subs = {'foo':'bat yat spam and eggs yer ber zat zam zer',
>             'bar':'bat yat spam and eggs yer ber',
>             'baz':'zat zam zer',
>             'bam':'yat spam and eggs yer',
>             'yam':'spam and eggs'}
> 
> I can assume that there is no mutual recursion of substitutions to make
> thing blow up.

i came up with three solutions of which i quote two here:

One is subclassing dict (which may be nice if you want to add
other stuff):

class sdict(dict):
    def subst(self, k=None):
        try: self[k] = " ".join(map(self.subst, self[k].split()))
        except KeyError: return k or map(self.subst, self)
        else: return self[k]

used like this:

    d = sdict(subs)
    res = d.subst('foo')  # expand everything neccessary for 'foo'
    d.subst()             # expand everything


or you can use the following function which also modifies in place:

def xget(d, k=None):
    f = lambda x: xget(d,x)
    try:
        d[k] = " ".join(map(f, d[k].split()))
        return d[k]
    except KeyError:
        return k or map(f, d)


Obviously those two are related but subclassing dict is nicer 
for use with 'map' and friends.     

> I know I can do this with a while loop and a "nothing_left_to_do"
> monitor variable, and some nested '.items()' loops.  But that looks like
> a mess.  It really seems like I should be able to do this with one or
> two lines of an amazing listcomp or map().

I hope the above fits your idea.  I tested it only with your 'subs' 
example dictionaries, btw. 

Now on to bug hunting :-)

yours,

    holger




More information about the Python-list mailing list