On Mon, 4 Jul 2005, Ron Adam wrote:

> George Sakkis wrote:
>
>> And finally for recursive flattening:
>> 
>> def flatten(seq):
>>     return reduce(_accum, seq, [])
>> 
>> def _accum(seq, x):
>>     if isinstance(x,list):
>>         seq.extend(flatten(x))
>>     else:
>>         seq.append(x)
>>     return seq
>> 
>> 
>>>>> flatten(seq)
>> 
>> [1, 2, 3, 4, 5, 6]
>
> How about this for a non recursive flatten.
>
> def flatten(seq):
>    s = []
>    while seq:
>        while isinstance(seq[0],list):
>            seq = seq[0]+seq[1:]
>        s.append(seq.pop(0))
>    return s
>
> seq = [[1,2],[3],[],[4,[5,6]]]
> flatten(seq)

The trouble with these is that they make a lot of temporary lists - 
George's version does it with the recursive calls to flatten, and Ron's 
with the slicing and concatenating. How about a version which never makes 
new lists, only appends the base list? We can use recursion to root 
through the lists ...

def isiterable(x):
        return hasattr(x, "__iter__") # close enough for government work

def visit(fn, x): # perhaps better called applytoall
        if (isiterable(x)):
                for y in x: visit(fn, y)
        else:
                fn(x)

def flatten(seq):
        a = []
        def appendtoa(x):
                a.append(x)
        visit(appendtoa, seq)
        return a

If you hate recursion, you can write a non-recursive version of visit; 
you'll have to manage a stack of lists yourself, though. Something like:

def visit(fn, x):
        if (not isiterable(x)): x = (x,)
        stack = [None] # stack of iterators
        cur = iter(x) # current iterator
        while (cur != None):
                try:
                        thing = cur.next()
                        if (isiterable(thing)):
                                stack.append(cur)
                                cur = iter(thing)
                        else:
                                fn(thing)
                except StopIteration:
                        cur = stack.pop()

There might be a cleverer way to do this.

tom

-- 
The revolution will not be televised. The revolution will be live.
-- 
http://mail.python.org/mailman/listinfo/python-list

Reply via email to