Beefy Boxes and Bandwidth Generously Provided by pair Networks
Your skill will accomplish
what the force of many cannot
 
PerlMonks  

Data::Rmap to modify an arrayref of arrayrefs

by metaperl (Curate)
on Jul 01, 2011 at 21:36 UTC ( #912416=perlquestion: print w/ replies, xml ) Need Help??
metaperl has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to get Data::Rmap to change this:
[ 'note', [ 'shopping', [ 'item' ] ] ];
to this:
[ 'note', [ 'shopping', [ item => 'bread' ], [ item => 'butter' ], [ item => 'beans' ], ] ];
But for some reason, it's not working out, even though I think it should per my commented code below:
use strict; use warnings; use Data::Rmap qw(:all); my $initial = [ note => [ shopping => [ 'item' ] ] ]; use Data::Dumper; my ($dump) = rmap_array { # If we get an arrayref whose first element is 'shopping' if ($_->[0] eq 'shopping') { my @item; # build a list of shopping items for my $item qw(bread butter beans) { push @item, [ item => $item ]; } # create a new array with those items my $newdata = [ shopping => \@item ]; # return immediately with new data, not visiting children # of this array cut($newdata) } else { # if the arrayrefs first element is not 'shopping' # then simply pass it through $_; } } $initial ; warn Dumper($initial, $dump);




The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

-- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

Comment on Data::Rmap to modify an arrayref of arrayrefs
Select or Download Code
Re: Data::Rmap to modify an arrayref of arrayrefs
by Khen1950fx (Canon) on Jul 02, 2011 at 00:00 UTC
    It wouldn't do  'item' => 'bread' but it would do bread =>. This was as close as I could get:
    #!/usr/bin/perl use strict; use warnings; use Data::Rmap qw(:all); my @item = ('bread', 'butter', 'beans'); my $initial = [ note => [ shopping => [ $item[0] => $item[1] => $item[2] => ], ], ]; use Data::Dumper; my ($dump) = rmap_array { if ($_->[0] eq 'shopping') { my @item; for my $item qw(bread butter beans) { push @item, [ item => $item ]; } my $newdata = [ shopping => \@item ]; cut($newdata) } else { $_; } } my @item ; warn Dumper($initial, $dump);
    Updated: fixed typo
Re: Data::Rmap to modify an arrayref of arrayrefs
by kcott (Abbot) on Jul 02, 2011 at 02:14 UTC

    I haven't used Data::Rmap before so others may have better answers. However, the following works and solves your problem.

    use strict; use warnings; use Data::Rmap qw(:all); my $initial = [ note => [ shopping => [ 'item' ] ] ]; use Data::Dumper; # build a list of shopping items ** for reuse ** my @shopping_items; for my $item qw(bread butter beans) { push @shopping_items, [ item => $item ]; } my ($dump) = rmap_array { # If we get an arrayref whose first element is 'shopping' if ($_->[0] eq 'shopping') { # Make the second element the shopping list $_->[1] = [ @shopping_items ]; # No need to drill down any further cut($_); } else { # if the arrayrefs first element is not 'shopping' # then simply pass it through $_; } } $initial; warn Dumper($initial, $dump);

    -- Ken

      Thanks kcott. I've gone ahead and abstracted htis into a function. Now, I'm going to try to solve it at the level of 'items' instead of at the parent level.
      use strict; use warnings; use Data::Rmap qw(:all); use Data::Dumper; my $initial_lol = [ note => [ shopping => [ item => 'sample' ] ] ]; # In $initial_lol, the new child of shopping is shopping_items my $new_lol = newchild($initial_lol, shopping => shopping_items()); warn Dumper($new_lol); sub newchild { my ($lol, $parent_arrayref_label, $new_child)=@_; my ($mapresult) = rmap_array { if ($_->[0] eq $parent_arrayref_label) { $_->[1] = $new_child; cut($_); } else { $_; } } $lol; $mapresult; } sub shopping_items { my @shopping_items; for my $item qw(bread butter beans) { push @shopping_items, [ item => $item ]; } \@shopping_items; }




      The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

      -- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

        tada! now I work at the item level instead of it's parent:
        use strict; use warnings; use Data::Rmap qw(:all); use Data::Dumper; my $initial_lol = [ note => [ shopping => [ item => 'sample' ] ] ]; # In $initial_lol, the new child of shopping is shopping_items my $new_lol = newnode($initial_lol, item => shopping_items()); warn Dumper($new_lol); sub newnode { my ($lol, $node_label, $new_node)=@_; my ($mapresult) = rmap_array { if ($_->[0] eq $node_label) { $_ = shopping_items(); cut($_); } else { $_; } } $lol; $mapresult; } sub shopping_items { my @shopping_items; for my $item qw(bread butter beans) { push @shopping_items, [ item => $item ]; } \@shopping_items; }




        The mantra of every experienced web application developer is the same: thou shalt separate business logic from display. Ironically, almost all template engines allow violation of this separation principle, which is the very impetus for HTML template engine development.

        -- Terence Parr, "Enforcing Strict Model View Separation in Template Engines"

Re: Data::Rmap to modify an arrayref of arrayrefs
by GrandFather (Cardinal) on Jul 02, 2011 at 02:21 UTC

    The trick seems to be to replace the 'items' sub-element:

    use strict; use warnings; use Data::Dump qw(); use Data::Rmap qw(); my $initial = [note => [shopping => ['item']]]; Data::Rmap::rmap_array { return $_ if $_->[0] ne 'shopping'; # Ignore non-shopping entries my @item= map {[item => $_]} qw(bread butter beans); $_->[1] = ['shopping', @item]; Data::Rmap::cut ($_); } $initial; print Data::Dump::dump ($initial), "\n";

    Prints:

    [ "note", [ "shopping", [ "shopping", ["item", "bread"], ["item", "butter"], ["item", "beans"], ], ], ]
    True laziness is hard work

        The structure may not be right, but the sense is and I see your solution takes elements from my code so it wasn't all loss was it? You may find the following trivial variant more to your liking:

        use strict; use warnings; use Data::Dump qw(); use Data::Rmap qw(); my $initial = [note => [shopping => ['item']]]; Data::Rmap::rmap_array { return $_ if $_->[0] ne 'shopping'; # Ignore non-shopping entries my @item= map {[item => $_]} qw(bread butter beans); $_ = ['shopping', @item]; Data::Rmap::cut ($_); } $initial; print Data::Dump::dump ($initial), "\n";

        prints:

        [ "note", [ "shopping", ["item", "bread"], ["item", "butter"], ["item", "beans"], ], ]
        True laziness is hard work
Re: Data::Rmap to modify an arrayref of arrayrefs
by metaperl (Curate) on Jul 02, 2011 at 10:43 UTC

      Why:

      } else { $_ = $_;

      which does nothing, and why:

      my $newdata = [ shopping => \@item ]; $_ = $newdata;

      when you could just:

      $_ = [ shopping => \@item ];

      or maybe even:

      $_ = [shopping => [map {[item => $_]} qw(bread butter beans)]];

      for the whole if block.

      True laziness is hard work
Re: Data::Rmap to modify an arrayref of arrayrefs
by Khen1950fx (Canon) on Jul 02, 2011 at 22:57 UTC
    I tried it without
    } else { $_ = $_; }
    It didn't work. I tried return in its place, but that also doesn't work, so I just used $_;.
    #!/usr/bin/perl use strict; use warnings; use Data::Rmap qw(:all); use Data::Dump qw(dump); use Storable qw(dclone); my $initial = ['note', ['shopping', ['item']]]; my $clone = dclone $initial; my($dump) = rmap_all { if( ref and $_->[0] eq 'shopping' ) { my @item = map { [ 'item' => '=>' => $_ ] } qw(bread butter beans) +; my $newdata = [ shopping => \@item ]; $_ = $newdata; } else { $_ } } $clone; print dump($dump);

Log In?
Username:
Password:

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

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

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (248 votes), past polls