Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Flatten sparse AoA

by FloydATC (Hermit)
on Jan 22, 2012 at 17:25 UTC ( #949265=perlquestion: print w/ replies, xml ) Need Help??
FloydATC has asked for the wisdom of the Perl Monks concerning the following question:

I have a "sparse" AoA ref where each element may be either defined or undefined. I can flatten the entire structure using

@flat = map { @$_ } @{$aoa};

but is there a more efficient way to eliminate all the undefs right there inside the map() so I won't have to loop through the @flat array or invoke grep() to do it for me?

@flat = grep { defined } map { @$_ } @{$aoa};

I don't really know if this is even an issue, I'm just curious since practical uses of map() have always been a bit of a mystery for me.

-- Time flies when you don't know what you're doing

Comment on Flatten sparse AoA
Select or Download Code
Re: Flatten sparse AoA
by moritz (Cardinal) on Jan 22, 2012 at 18:29 UTC

    You can save a bit of memory by first grepping for defined elements inside each array, and then combining them:

    my @flat = map { grep defined, @$_ } @{$aoa};

    That way the "big" list with all the elements, including the undefs, isn't fully created in the first place.

Re: Flatten sparse AoA
by Marshall (Prior) on Jan 22, 2012 at 18:47 UTC
    I'm not sure if this is more efficient or not with recent Perl versions, but a thing that is not so obvious is that to return "nothing" from a map, return ();
    my @flat = map { (defined @$_) ? @$_ : () )@{$aoa};
      That does something else then what the OP does. You're filtering out the undefined elements of @$aoa (that is, top level elements), while the OP wants to remove (according to his code), the undefined elements of the elements of @$aoa.

      That is, if $aoa is

      [ [2, undef, 4], [undef, undef, 5], ];
      he wants to end with
      (2, 4, 5)
      not with
      (2, undef, 4, undef, undef, 5)
      which is what your code ends up with.

      Note that you probably intended to write defined $_ instead of defined @$_.

        Yes, thank you.

        Update:

        #!/usr/bin/perl -w use strict; use Data::Dumper; $|++; my @AoA = ( undef, [1, 2], undef, [3, 4]); my @flat = map{defined (@$_) ? @$_ : ()}@AoA; print join (",",@flat),"\n"; # prints: 1,2,3,4 my $AoAref = \@AoA; @flat = map{ defined (@$_) ? @$_ : () }@$AoAref; print join (",",@flat),"\n"; # prints: 1,2,3,4 =so far prints:... 1,2,3,4 1,2,3,4 =cut @AoA = ( undef, [1, undef], undef, [3, 4]); $AoAref = \@AoA; # "undef" is a legal Perl value. # to handle this idea of an undef value within # an defined array (undef is a legal Perl value)! Yes, use grep. # # my map filters out "undefined references to arrays" # within an AoA, I would use grep to filter # that undesired "undef" value out if what is meant # a value within in an array. # as shown before: grep{} map{}.
        My code is just a special case.
        The more general case is to flatten the whole thing out and grep out the undefined values provided that if what is meant by "sparse" is that not only entire rows are missing but also columns within defined rows. "undef" is a legal Perl value and requires some kind of "grep" to "get rid of it"
Re: Flatten sparse AoA
by educated_foo (Vicar) on Jan 22, 2012 at 21:56 UTC
    You (hopefully) meant
    @flat = map { @$_ } grep { defined } @{$aoa};
    and the answer is "no." If your array is truly sparse, you should implement it with a hash.
Re: Flatten sparse AoA
by jwkrahn (Monsignor) on Jan 22, 2012 at 22:15 UTC
    is there a more efficient way to eliminate all the undefs right there inside the map()
    my @flat = map defined ? @$_ : (), @$aoa;

    Or perhaps:

    my @flat = map ref eq 'ARRAY' ? @$_ : (), @$aoa;
Re: Flatten sparse AoA
by JavaFan (Canon) on Jan 23, 2012 at 00:19 UTC
    I would write:
    @flat = grep {defined} map {@$_} grep {$_} @AoA;
    This assumes each element of @AoA is either an arrayref, or an undefined value.

    I'm not the biggest fan of using EXPR ? LIST : () inside a map just to avoid writing grep.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://949265]
Approved by Old_Gray_Bear
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others taking refuge in the Monastery: (5)
As of 2014-07-31 10:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (248 votes), past polls