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!
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.
| [reply] [d/l] |
|
Getting an error: Not a HASH reference at...
| [reply] [d/l] |
|
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.
| [reply] [d/l] |
|
|
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'
};
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
|
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',
};
| [reply] [d/l] [select] |
|
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.
| [reply] [d/l] [select] |
|
| [reply] [d/l] |
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.
| [reply] |
Re: Add array ref to another array ref
by karlgoethebier (Abbot) on Jul 15, 2019 at 20:12 UTC
|
#!/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
| [reply] [d/l] [select] |
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 | [reply] [d/l] [select] |
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: <%-{-{-{-<
| [reply] [d/l] [select] |
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"
| [reply] [d/l] |
|
|