Beefy Boxes and Bandwidth Generously Provided by pair Networks
"be consistent"
 
PerlMonks  

Insert into element into arrays ref

by Anonymous Monk
on Aug 22, 2019 at 17:23 UTC ( #11104862=perlquestion: print w/replies, xml ) Need Help??

Anonymous Monk has asked for the wisdom of the Perl Monks concerning the following question:

Hi there Monks!

I need to insert the @$data2 value into the @$data1. The code I have only updates the first element in the @$data1:
#!/usr/bin/perl use strict; use warnings; use Data::Dumper; my $data1 = [ { 'NAME' => 'PAUL DY', 'DATE' => '2009-05-05', 'NUMBER' => '00001', }, { 'NAME' => 'ANTHONY RD', 'DATE' => '2012-01-07', 'NUMBER' => '00003', }, { 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07', 'NUMBER' => '00023', }, ]; my $data2 = [ { 'CODE' => 'X11', } ]; @$data1= ({map { %$_ } (@$data1, @$data2)}); print Dumper $data1;

Thanks for helping!

Replies are listed 'Best First'.
Re: Insert into element into arrays ref
by Fletch (Chancellor) on Aug 22, 2019 at 17:27 UTC

    No need to futz around with map. Just push the contents of @{$data2} onto @{$data1}.

    The cake is a lie.
    The cake is a lie.
    The cake is a lie.

      Using push:

      push @$data1, @$data2;

      Result:
      [ { 'DATE' => '2009-05-05', 'NAME' => 'PAUL DY', 'NUMBER' => '00001' }, { 'NAME' => 'ANTHONY RD', 'NUMBER' => '00003', 'DATE' => '2012-01-07' }, { 'NUMBER' => '00023', 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07' }, { 'CODE' => 'X11' } ]

      Looking for this:
      [ { 'NAME' => 'PAUL DY', 'DATE' => '2009-05-05', 'NUMBER' => '00001', 'CODE' => 'X11', }, { 'NAME' => 'ANTHONY RD', 'DATE' => '2012-01-07', 'NUMBER' => '00003', 'CODE' => 'X11', }, { 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07', 'NUMBER' => '00023', 'CODE' => 'X11', }, ]

      Thanks!

        One way (update: see the Perl Data Structures Cookbook):

        c:\@Work\Perl\monks>perl use strict; use warnings; use Data::Dumper; my $data1 = [ { 'NAME' => 'PAUL DY', 'DATE' => '2009-05-05', 'NUMBER' => '00001', }, { 'NAME' => 'ANTHONY RD', 'DATE' => '2012-01-07', 'NUMBER' => '00003', }, { 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07', 'NUMBER' => '00023', }, ]; my $data2 = [ { 'CODE' => 'X11', } ]; foreach my $hashref (@$data1) { %$hashref = (%$hashref, %{ $data2->[0] }); } print Dumper $data1; __END__ $VAR1 = [ { 'NAME' => 'PAUL DY', 'DATE' => '2009-05-05', 'CODE' => 'X11', 'NUMBER' => '00001' }, { 'NAME' => 'ANTHONY RD', 'DATE' => '2012-01-07', 'CODE' => 'X11', 'NUMBER' => '00003' }, { 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07', 'CODE' => 'X11', 'NUMBER' => '00023' } ];

        Update 1: Note that using this method, if there is a key in the hash referent of the single element of the  $data2 array referent that is the same as one in a hash referent of any  $data1 array referent, the value of the former will silently overwrite the value of the latter. (Update: For instance, see what happens if  $data2 happens to be
            my $data2 = [ { 'CODE' => 'X11',  'NAME' => 'JONES', } ];
        instead. (Update: This exact problem is discussed more clearly in the FAQ referenced by BillKSmith here.))

        Update 2: Here's a testing framework for playing around with other approaches. See Test::More, Test::NoWarnings.


        Give a man a fish:  <%-{-{-{-<

        You are merging the hash in $data2 with each of the hashes in $data1. Read the FAQ.
        perldoc -q "How do I merge two hashes?"
        Bill
Re: Insert into element into arrays ref
by NetWallah (Canon) on Aug 23, 2019 at 00:15 UTC
    Another way - UPDATING the contents of $data1 without replacing them,
    and arguably easier on the eyes:
    while(my($k,$v)=each %{$data2->[0]}){ $_->{$k} = $v for @$data1; }
    UPDATE: Changed "for" to "while" to accomodate multi-key hashref in $data2, per aartist (++).

                    "From there to here, from here to there, funny things are everywhere." -- Dr. Seuss

      for (my($k,$v)=each %{$data2->[0]}){ $_->{$k} = $v for @$data1; }

      That works for a single key/value element in $data2->[0], but given that it can work for only a single element, why not use the ocularly even easier

      my ($k,$v) = %{$data2->[0]}; $_->{$k} = $v for @$data1;

      c:\@Work\Perl\monks>perl use strict; use warnings; use Data::Dumper; my $data1 = [ { 'NAME' => 'PAUL DY', 'DATE' => '2009-05-05', 'NUMBER' => '00001', }, { 'NAME' => 'ANTHONY RD', 'DATE' => '2012-01-07', 'NUMBER' => '00003', }, { 'NAME' => 'RUTH RD', 'DATE' => '2018-01-07', 'NUMBER' => '00023', }, ]; my $data2 = [ { 'CODE' => 'X11', 'X' => 'Y', } ]; for (my($k,$v)=each %{$data2->[0]}){ $_->{$k} = $v for @$data1; } print Dumper $data1; __END__ $VAR1 = [ { 'NAME' => 'PAUL DY', 'X' => 'Y', 'DATE' => '2009-05-05', 'NUMBER' => '00001' }, { 'NAME' => 'ANTHONY RD', 'X' => 'Y', 'DATE' => '2012-01-07', 'NUMBER' => '00003' }, { 'NAME' => 'RUTH RD', 'X' => 'Y', 'DATE' => '2018-01-07', 'NUMBER' => '00023' } ];


      Give a man a fish:  <%-{-{-{-<

        for (my($k,$v)=each %{$data2->[0]}){

        You may need to use while in place of for to get all the value in %{$data2->[0]}

Re: Insert into element into arrays ref
by aartist (Pilgrim) on Aug 23, 2019 at 10:43 UTC
    We need to change the object pointed by each hashref of data1. It accommodates for multiple key/values in data2.
    for my $hash1 (@{$data1}){ for my $hash2 (@{$data2}){ for my $key (keys %$hash2){ $hash1->{$key}=$hash2->{$key}; } } } print Dumper $data1;
      It accommodates for multiple key/values in data2.

      It accommodates multiple hashes in  $data2 with each hash having multiple key/values! This exceeds the implied requirement of the OP, but I find that requirements tend to expand spontaneously in these situations anyway.

      I was a bit daunted by the time-complexity of the triple nesting of your solution. I tried to come up with some alternatives. I think these all work, but neither your solution nor any of mine have been thoroughly tested by me. Unfortunately, I think the big-Os of all these solutions, yours and mine, are going to turn out to be exactly the same!

      foreach my $hashref (@$data1) { %$hashref = (%$hashref, %$_) for @$data2; } for my $hash1 (@$data1) { @{ $hash1 }{ keys %$_ } = values %$_ for @$data2; } foreach my $hash1 (@$data1) { for my $hash2 (@$data2) { map { $hash1->{$_} = $hash2->{$_} } keys %$hash2; } } for my $hash1 (@$data1) { for my $hash2 (@$data2) { while (my ($k2, $v2) = each %$hash2) { $hash1->{$k2} = $v2; } } }


      Give a man a fish:  <%-{-{-{-<

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://11104862]
Approved by Discipulus
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 2020-01-29 15:04 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?
    Notices?