Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Recursively mirroring a nested tuple in Python

I was trying to write a function that inputs a nested tuple and returns a tuple where all the elements are backwards, including those elements in other tuples (basically mirrors it). So with this input:

((1, (2, 3)), (4, 5))

It should return:

((5, 4), ((3, 2), 1))

What I tried

def mirror(t):
    n = 1
    for i in t:
        if isinstance(i, tuple):
            mirror(i)
        if n == len(t):
            t = list(t)
            t = t[::-1]
            t = tuple(t)
        n += 1
    return t
like image 786
shindeiru Avatar asked Jan 15 '18 09:01

shindeiru


2 Answers

The trickiness of this problem lies in the fact that tuple objects are immutable. One solution I can think of is recursively building each piece in the final reversed result, and then using itertools to join them together.

from itertools import chain

def mirror(data):
    r = []
    for t in reversed(data):
        if isinstance(t, tuple):
            t = mirror(t)
        r.append((t, ))

    return tuple(chain.from_iterable(r))

>>> mirror(((1, (2, 3)), (4, 5)))
((5, 4), ((3, 2), 1))

Thanks to Chris_Rands for the improvement.


Here's a simpler solution, courtesy PM2 Ring -

def mirror(t):
    return tuple(mirror(u) for u in t[::-1]) if isinstance(t, tuple) else t

>>> mirror(((1, (2, 3)), (4, 5)))
((5, 4), ((3, 2), 1))

It builds the result tuple recursively but using a gen comp.

like image 34
cs95 Avatar answered Nov 14 '22 21:11

cs95


Maybe I'm missing something, but I think it can be done relatively simply:

def mirror(data):
    if not isinstance(data, tuple):
        return data
    return tuple(map(mirror, reversed(data)))

>>> mirror(((1, (2, 3)), (4, 5)))
((5, 4), ((3, 2), 1))

This applies the mirror function to every element in the tuple, combining them into one new tuple in reverse order.

like image 135
khelwood Avatar answered Nov 14 '22 21:11

khelwood