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

Add array ref to another array ref

by Anonymous Monk
on Jul 15, 2019 at 18:17 UTC ( [id://11102877]=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 am trying to add $data_a to $data_b to have the $data_b as:
my $data_b = { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', };

Here are some data sample:
my $data_a = { 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', }; my $data_b = { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', };
If I use  push @{ $data_b }, $data_a; It will give this instead:
my $data_b =[ { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', }, { 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', }; ];

Which isn't what I am looking for, any suggestions?

Thanks for looking!

Replies are listed 'Best First'.
Re: Add array ref to another array ref
by holli (Abbot) on Jul 15, 2019 at 18:23 UTC
    Just overwrite the original hash with a merge of both hashes.
    $data_a = { %$data_a, %$data_b };


    holli

    You can lead your users to water, but alas, you cannot drown them.
      Getting an error: Not a HASH reference at...
        Then your data is different from what you tell us:
        D:\ENV>perl -MData::Dumper -e "$ha = { a => 'A' }; $hb = { b => 'B' }; + $m = { %$ha, %$hb }; print Dumper( $m );" $VAR1 = { 'b' => 'B', 'a' => 'A' };


        holli

        You can lead your users to water, but alas, you cannot drown them.
Re: Add array ref to another array ref
by stevieb (Canon) on Jul 15, 2019 at 18:57 UTC

    You're working on hashes (hash references, actually), not arrays (array references). There's a significant difference, and push() is used on arrays, which is why you got a collection of hash references within a new array reference. Note that hashes are sometimes referred to as "associative array", which is not the same thing as a normal array.

    Here's two ways to do what you want. I created a new hash ref ($hash_c) so I didn't clobber $hash_b before doing the second example. The result is the same though. The first example uses map(), and if both $hash_a and $hash_b both have a key with the same name, the one in $hash_b will be overwritten with $hash_a's value. The second example does a key/value add, but if $hash_b already has a key in $hash_a, we'll just skip it and keep $hash_b's value:

    use warnings; use strict; use Data::Dumper; my $data_a = { 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', }; my $data_b = { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', }; my $data_c; %{ $data_c } = map { $_ => $data_a->{$_} } keys %$data_b, keys %$data_ +a; for my $k (keys %$data_a){ $data_b->{$k} = $data_a->{$k} if ! exists $data_b->{$k}; } print Dumper $data_c; print Dumper $data_b;

    Output:

    $VAR1 = { 'house' => undef, 'code' => undef, 'fullname' => 'Ms Mary Lou', 'last' => 'Lou', 'area' => undef, 'first' => 'Mary', 'number' => undef }; $VAR1 = { 'first' => 'Mary', 'number' => '0123', 'house' => 'main', 'code' => 'zip', 'fullname' => 'Ms Mary Lou', 'last' => 'Lou', 'area' => 'north' };

      Trying to push onto a hashref will produce an error so my guess is that $data_b is coming back from wherever as an AoH to begin with.

      DB<1> $a = { qw/ foo bar/ } DB<2> $b = { qw/baz quux/ } DB<3> x +{ %$a, %$b } 0 HASH(0x7ff1242138f0) 'baz' => 'quux' 'foo' => 'bar' DB<4> x push @{ $b }, $a Not an ARRAY reference at (eval 17)[/System/Library/Perl/5.18/perl5db. +pl:732] line 2.

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

      I am getting confused with the data types.
      I did a data dumper on $data_b and got this:
      $VAR1 = [ { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', }; ]

      And on $data_a was this:
      $VAR1 = { 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', };

        When you see the square brackets [], that's an arrayref (a reference to an array). When you see braces {}, that's a hashref (a reference to a hash).

        So the first VAR1 that you see is an arrayref with a single element, which is a hashref. The second VAR1 is just a hashref.

        Alex / talexb / Toronto

        Thanks PJ. We owe you so much. Groklaw -- RIP -- 2003 to 2013.

        Please see this, especially the Update.


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

Re: Add array ref to another array ref (actually hashrefs)
by hippo (Bishop) on Jul 15, 2019 at 21:22 UTC

    It's an FAQ! How do I merge two hashes?

    If you have hashrefs rather than hashes you will additionally need to handle the dereferencing of course, but the principle is the same.

Re: Add array ref to another array ref
by karlgoethebier (Abbot) on Jul 15, 2019 at 20:12 UTC

    I guess what you really want is to merge two hash refs. Corion wrote this 11 years ago. You might try something like this:

    #!/usr/bin/env perl use strict; use warnings; use Hash::Merge qw(merge); use Data::Dump; use Test::More tests => 1; my $data_a = { 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', }; my $data_b = { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', }; my $expected = { 'house' => 'main', 'number' => '0123', 'area' => 'north', 'code' => 'zip', 'fullname' => 'Ms Mary Lou', 'first' => 'Mary', 'last' => 'Lou', }; dd $data_a; dd $data_b; dd $expected; my $result = merge( $data_a, $data_b ); dd $result; is_deeply( $result, $expected, qq(merged hash refs) ); __END__ Karls-Mac-mini:Desktop karl$ ./merge.pl 1..1 { first => "Mary", fullname => "Ms Mary Lou", last => "Lou" } { area => "north", code => "zip", house => "main", number => "0123" } { area => "north", code => "zip", first => "Mary", fullname => "Ms Mary Lou", house => "main", last => "Lou", number => "0123", } { area => "north", code => "zip", first => "Mary", fullname => "Ms Mary Lou", house => "main", last => "Lou", number => "0123", } ok 1 - merged hash refs

    Please see also Hash::Merge, Test::More and Data::Dump. A look at ref might be probably useful as well. Best regards, Karl

    «The Crux of the Biscuit is the Apostrophe»

    perl -MCrypt::CBC -E 'say Crypt::CBC->new(-key=>'kgb',-cipher=>"Blowfish")->decrypt_hex($ENV{KARL});'Help

Re: Add array ref to another array ref
by Don Coyote (Hermit) on Jul 15, 2019 at 21:44 UTC

    You are accessing the hashref as an arrayref, and then pushing data onto an array that now holds a ref to a hash %$data_b as the first item. You need to access the hashref in a slightly different way to a single element list arrayref.

    Elements are acccessed from the inside out rather than the outside in. To 'push' on to hashes you may like to do something like this. Using the keyword each

    use diagnostics -verbose; while( my ( $key, $value ) = each %$data_a ){ $data_b->{ $key } = $value } printf "%10s%12s\n", 'key:', ':value'; while( my ( $k, $v ) = each %$data_b ){ my $c; printf "%9s%-8s%-11s\n", $k, ++$c % 2 == 1 ? ' --- ' : '', $v; } __END__ key: :value house --- main first Mary number --- 0123 area north fullname --- Ms Mary Lou last Lou code --- zip

    Also regarding Not A Hash error, try commenting out the push @{ $data_b }, ... line first. By accessing it as an array, you have wrapped it in an anonymous array. Which it now thinks it is.

    # <- comment # push @{ $data_b }, $actually_im_not_parsed

    Went swimming in the C and found a Perl
Re: Add array ref to another array ref
by AnomalousMonk (Archbishop) on Jul 15, 2019 at 19:46 UTC
    If I use  push @{ $data_b }, $data_a; It will give ...
    ...
    Which isn't what I am looking for ...

    But you never say in any of your posts what you are looking for. What is the final structure you want given your example inputs?


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

Re: Add array ref to another array ref
by BillKSmith (Monsignor) on Jul 16, 2019 at 14:59 UTC
    After you succeed in merging two hashes, the keys will be in random order. If this is a problem, refer to FAQ:
    perdoc -q "How do I sort a hash"
    Bill

Log In?
Username:
Password:

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

How do I use this?Last hourOther CB clients
Other Users?
Others browsing the Monastery: (4)
As of 2024-04-25 18:00 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    No recent polls found