Code Snippets

This is a new section dedicated to small snippets (well, just one so far) of code I've written that I am particularly fond of...

Recurion & Generators

This is the description of the problem.

    Given a data struct like this:

    x = {
        'lion':['a','b'],
        'tiger':['m','o'],
        'cheetah':['y','z'],
        }

    I want to end up with this:

    y = [
        { 'lion':'a', 'tiger':'m', 'cheetah':'y', },
        { 'lion':'a', 'tiger':'m', 'cheetah':'z', },
        { 'lion':'a', 'tiger':'o', 'cheetah':'y', },
        { 'lion':'a', 'tiger':'o', 'cheetah':'z', },

        { 'lion':'b', 'tiger':'m', 'cheetah':'y', },
        { 'lion':'b', 'tiger':'m', 'cheetah':'z', },
        { 'lion':'b', 'tiger':'o', 'cheetah':'y', },
        { 'lion':'b', 'tiger':'o', 'cheetah':'z', },
        ]
    

And here is what I came up with. I really like how generators and recursion play well together. Makes for an elegant solution IMO.

    def combinator(items):
        expanded = [[(key,v) for v in values] for key,values in items]
        return (dict(l) for l in _citer(expanded))

    def _citer(lst):
        head,tail = lst[0],lst[1:]
        if not tail:
            for t in head:
                yield [t]
        else:
            for t in head:
                for h in _citer(tail):
                    yield [t] + h

    if __name__=="__main__":
        from pprint import pprint
        val = combinator(x.items())
        pprint(val)