Beefy Boxes and Bandwidth Generously Provided by pair Networks
Just another Perl shrine
 
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 (Sage) 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 exploiting the Monastery: (5)
As of 2015-07-04 22:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (60 votes), past polls