in reply to Re: Re: flattening a list-of-lists
in thread flattening a list-of-lists

Updated: It now includes checking for cycles.

That seems way complicated. I went with:

*isa = \&UNIVERSAL::isa; sub flatten { my @stack= reverse @_; my %seen; my @out; while( @stack ) { my $value= pop(@stack); if( !ref($value) || !isa($value,"ARRAY") ) { push @out, $value; } elsif( ! $seen{0+$value}++ ) { push @stack, reverse @$value; } } return @out; } sub flatten2 { my @out; my %seen; while( @_ ) { my $value= shift(@_); if( !ref($value) || !isa($value,"ARRAY") ) { push @out, $value; } elsif( ! $seen{0+$value}++ ) { unshift @_, @$value; } } return @out; } my @list = ( 1, [ 2, 3 ], 4, [ [ 5, 6 ], 7, [ 8 ] ] ); print join " ", flatten( @list, @list ); print $/; print join " ", flatten2( @list, @list ); print $/;
which outputs:
1 2 3 4 5 6 7 8 1 4 1 2 3 4 5 6 7 8 1 4

                - tye

Replies are listed 'Best First'.
Re: Re^3: flattening a list-of-lists (simpler)
by demerphq (Chancellor) on Nov 19, 2003 at 22:39 UTC

    I think its arguable that mine is closer to what (I see) is the spirit of L~R's original intention. That being to minimize the amount overhead especially that associated with the stack. I thought of using this approach, but decided against on the grounds that it involved an unreasonable amount of copying and stack manipulation. Heh. Whatever. In real life I would just use recursion on this most likely. :-)

    Caveats about using is() and 0+$ref in the algorithm of course. Better to use Scalar::Util or parse overload::StrVal(). But you knew that, and its beside the point here isnt it. :-)


    ---
    demerphq

      First they ignore you, then they laugh at you, then they fight you, then you win.
      -- Gandhi