I figured I'd start a series of Python challenges in my blog. Whenever I've posted questions such as these in the past, the discussion that follows is always very entertaining!

A discussion arose today at work about the best way to flatten a tuple consisting of values and other tuples (which may be nested arbitrarily). So the tuple (1, (1, 2, (1, 2, 3), 3)) would become (1, 1, 2, 1, 2, 3, 3). Now there was actually code implemented which was functional, efficient and easy to read – but where is the fun in that?

I figured I could re-write it in a more terse manner, and here is what I came up with:

def flatten(tpl):
    return eval(repr(tpl).replace('(', '').replace(')', ''))

t= (1, (1, 2, (1, 2, 3), 3))
print flatten(t)

This flatten function would actually work in the context of our app, but I would never use it in production code. My challenge today, is to tell me why this code should never be used!

This blog post was posted to It's All Geek to Me on Thursday March 12th, 2009 at 6:24PM
 

11 Responses to "Nesting Instinct"

  • pythonista
    March 12th, 2009, 7:55 p.m.

    You could have string values (for example) with parenthesis in them. These values would be changed.

  • March 12th, 2009, 7:58 p.m.

    A further reason is that you have no idea what the repr of the object looks like, since you don't even examine its type …

    One must hope nobody starts devising malicious objects with exploitive repr()s.

    Cute idea, though.

  • Euan Goddard
    March 12th, 2009, 8:51 p.m.

    I can't believe you had the audacity to post that! Very amusing though. Let me know when you can properly do it in 2 lines

  • March 12th, 2009, 9:19 p.m.

    How about this, Euan…

    def flatten(tpl):
    return sum(map(flatten, tpl), ()) if type(tpl) is tuple else (tpl,)

    t= (1, (1, 2, (1, 2, 3), 3))
    print flatten(t)

    Not quite as concise as the the other flatten, but less of a crime against Python!

  • jdm
    March 12th, 2009, 9:40 p.m.

    2euan: is this “properly”?

    def flatten(tpl):
    return reduce(lambda x,y: x+flatten(y),tpl,()) if type(tpl) is tuple else (tpl,)

  • March 12th, 2009, 9:49 p.m.

    A safe variant of your solution, assuming the values are integers:

    def flatten(tpl):

    return tuple( map(int, repr(tpl).replace('(', ‘').replace(’)', ‘').split(’, ')) )

  • March 12th, 2009, 9:50 p.m.

    Posting again, sorry:

    def flatten(tpl):
    return tuple( map(int, repr(tpl).replace('(', '').replace(')', '').split(', ')) )

  • jdm
    March 12th, 2009, 9:52 p.m.

    oops, didn't see Will's, which is cleaner.

  • March 13th, 2009, 5:22 a.m.

    Since I've been glancing at the Y combinator [paddy3118.blogspot.com]

    >>> t= (1, (1, 2, (1, 2, 3), 3))
    >>> _smash = lambda f: lambda t: sum(map(f, t), ()) if type(t) is tuple else (t,)
    >>> Y = lambda f: (lambda x: x(x))(lambda y: f(lambda z: y(y)(z)))
    >>> # From two non recursive functions:
    >>> smash = Y(_smash)
    >>> smash(t)
    (1, 1, 2, 1, 2, 3, 3)
    >>>

    Remember: Don't do this at home folks :-)

    - Paddy.

  • March 13th, 2009, 8:34 a.m.

    One liner variation, working with any iterable:

    flatten = lambda t: sum(map(flatten, t), ()) if hasattr(t, ‘__iter__’) else (t,)

  • Eno
    March 19th, 2009, 6:23 p.m.
    from itertools import chain

    flatten = lambda x :chain(*(flatten(v) if type(v) is tuple else (v,) for v in x))

    t = (1, (1, 2, (1, 2, 3), 3))
    print list(flatten(t))

    I recommend a visit to http://www.challenge-you.com [challenge-you.com] if you enjoy those kind of challenges.

Leave a Comment

You can use bbcode in the comment: e.g. [b]This is bold[/b], [url]http://www.willmcgugan.com[/url], [code python]import this[/code]
Preview Posting...
Previewing comment, please wait a moment...
Will McGugan

My name is Will McGugan. I am an unabashed geek, an author, a hacker and a Python expert – amongst other things!

You are reading my tech blog. See the homepage for my other blogs.

Search for Posts
Possibly related posts
Tags
Popular Tags
 
Archives
2010
 
Recent Comments
http://www.iclshoes.com/alexander-mcqueen-c-13.html [iclshoes.com] http://www.iclshoes.com/jimmy-choo-shoes-c-2.html [iclshoes.com] http://www.iclshoes.com/ [iclshoes.com] http://www.zentai-mart.com/Play-Costumes-c-5.html [zentai-mart.com] http://www.zentai-mart.com/Latex-Catsuits-Clothes-c-3.html [zentai-mart.com] http://www.zentai-mart.com/PVC-Catsuits-Clothes-c-6.html [zentai-mart.com] http://www.zentai-mart.com/ [zentai-mart.com] http://www.hereshoes.com/miu-miu-shoes-c-31.html [hereshoes.com] http://www.hereshoes.com/giuseppe-zanotti-c-43.html [hereshoes.com] http://www.hereshoes.com/lanvin-shoes-c-50.html [hereshoes.com] ...
- Christian Louboutin on Turning website favicons in to 3D
What are the charmings of?a href="http://www.iclshoes.com [iclshoes.com]cl shoes/a?They are quality,comfort and style.The a href=http://www.iclshoes.com/jimmy-choo-shoes-c-2.html [iclshoes.com]Jimmy Choo shoes/a are made from ...
- Christian Louboutin on Turning website favicons in to 3D
Thanks a lot for that: I had first tried sudo aptitude purge adobe-flashplugin then sudo aptitude install flashplugin-nonfree but that ...
Andre, the name is derived from the class name (camel case converted to lower case with underscores). But, you can ...
is this using some kind of name mangling to map sorethumb:rounded_corners_edged to the RoundedCornersEdged class? that seems a little unnecessary ...
 
© 2008 Will McGugan.

A technoblog blog, design by Will McGugan