Re: Combining two references
by Laurent_R (Canon) on Jun 08, 2015 at 17:48 UTC
|
jeffa's proposal is probably the simplest, but your code would work if you change the relevant line to:
push @{ $all }, @$data1, @$data2;
When I dump $all after this change, I get:
$VAR1 = [
{
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05',
'NUMBER' => '00001'
},
{
'NAME' => 'ANTHONY RD',
'DATE' => '2012-01-07',
'NUMBER' => '00003'
},
{
'CAR2' => '2',
'CAR1' => '1',
'CAR3' => '3'
},
{
'CAR2' => '2b',
'CAR1' => '1b',
'CAR3' => '3b'
}
];
i.e. presumably what you want.
| [reply] [d/l] [select] |
|
|
This did, is that a way to avoid printing "undef"s:
my $all;
push @{ $all }, @$data1, @$data2;
foreach my $row (@$all) {
my $name = $row->{ NAME };
my $date = $row->{ DATE };
my $number = $row->{ NUMBER };
my $car1 = $row->{ CAR1 };
my $car2 = $row->{ CAR2 };
my $car3 = $row->{ CAR3 };
warn Dumper $name,$date,$number,$car1,$car2,$car3;
}
Thanks! | [reply] [d/l] |
|
|
| [reply] |
|
|
|
|
|
|
|
|
Re: Combining two references
by jeffa (Bishop) on Jun 08, 2015 at 17:33 UTC
|
De-reference them as arrays inside an array reference, and assign that to a variable:
my $all = [ @$data1, @$data2 ];
print Dumper $all;
jeffa
L-LL-L--L-LL-L--L-LL-L--
-R--R-RR-R--R-RR-R--R-RR
B--B--B--B--B--B--B--B--
H---H---H---H---H---H---
(the triplet paradiddle with high-hat)
| [reply] [d/l] |
|
|
Trying this way and getting this error:
Not a HASH reference at...
my $all = [ $data1, $data2 ];
foreach my $row ( @{ $all } ) {
my $name = $row->{ NAME };
my $car1 = $row->{ CAR1 };
warn Dumper $name;
warn Dumper $car1;
}
| [reply] [d/l] [select] |
|
|
It fails because you kept the same buggy code instead of using jeffa's fix.
Again, the fix is to deference the arrays to get their elements: @$data1, @$data2
| [reply] [d/l] |
|
|
That will not work. Since you have a single hash within each array element (and the hashes have colliding key names), you have to extract each hash, and pull the NAME (CAR1 will fail as this hash doesn't have this key). However, the next iteration will overwrite NAME, and still fail on CAR1. On the following two iterations over the array, the exact opposite will happen.
You will have 'Undefined variable' warnings everywhere.
Why don't you state what it is that you want to do with the data in the end, and perhaps we can guide you to a data structure that fits your needs?
-stevieb
| [reply] |
Re: Combining two references
by thanos1983 (Parson) on Jun 08, 2015 at 22:08 UTC
|
Hello Anonymous,
Although that the other monks have already answered your question I would like to add something. Why not to use ARRAYS OF HASHES?
Sample of code provided under:
#!/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',
}
);
print Dumper \@data1;
=data1
$VAR1 = [
{
'NUMBER' => '00001',
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05'
},
{
'DATE' => '2012-01-07',
'NUMBER' => '00003',
'NAME' => 'ANTHONY RD'
}
];
=cut
my @data2 = (
{
'CAR1' => '1',
'CAR2' => '2',
'CAR3' => '3',
},
{
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b',
}
);
print Dumper \@data2;
=data2
$VAR1 = [
{
'CAR3' => '3',
'CAR1' => '1',
'CAR2' => '2'
},
{
'CAR3' => '3b',
'CAR1' => '1b',
'CAR2' => '2b'
}
];
=cut
push my @AoH , ( @data1 , @data2 );
=alternatively
my @AoH = ( @data1 , @data2 );
=cut
print Dumper \@AoH;
__END__
$VAR1 = [
{
'NUMBER' => '00001',
'DATE' => '2009-05-05',
'NAME' => 'PAUL DY'
},
{
'NUMBER' => '00003',
'NAME' => 'ANTHONY RD',
'DATE' => '2012-01-07'
},
{
'CAR3' => '3',
'CAR2' => '2',
'CAR1' => '1'
},
{
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b'
}
];
There are many ways to play around with these just try.
For example you can Making References with array of hashes.
Sample of code:
my $refAoH = \@AoH;
print Dumper $refAoH;
Same result as above.
Hope this helps.
Seeking for Perl wisdom...on the process of learning...not there...yet!
| [reply] [d/l] [select] |
|
|
Whats in your option should be the most efficient way to interact (loop) over this ARRAYS OF HASHES?
Thanks!
| [reply] |
|
|
| [reply] [d/l] [select] |
Re: Combining two references
by RichardK (Parson) on Jun 08, 2015 at 17:37 UTC
|
Firstly, which line is giving you that error ?
Secondly, why not dump $all to see what it contains?
see also : basic debugging checklist
| [reply] |
|
|
my $name = $row->{ NAME };
| [reply] [d/l] |
Re: Combining two references
by CountZero (Bishop) on Jun 09, 2015 at 16:06 UTC
|
use Modern::Perl qw/2015/;
use Data::Dump qw/dump/;
use List::MoreUtils qw/zip natatime/;
my $data1 = [
{
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05',
'NUMBER' => '00001',
},
{
'NAME' => 'ANTHONY RD',
'DATE' => '2012-01-07',
'NUMBER' => '00003',
},
];
my $data2 = [
{
'CAR1' => '1',
'CAR2' => '2',
'CAR3' => '3',
},
{
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b',
},
];
my @all;
my $it = natatime 2, zip @$data1, @$data2;
while (my ($first, $second) = $it->()) {
push @all, {%$first, %$second};
}
say dump @all;
Output:(
{
CAR1 => 1,
CAR2 => 2,
CAR3 => 3,
DATE => "2009-05-05",
NAME => "PAUL DY",
NUMBER => "00001",
},
{
CAR1 => "1b",
CAR2 => "2b",
CAR3 => "3b",
DATE => "2012-01-07",
NAME => "ANTHONY RD",
NUMBER => "00003",
},
)
CountZero A program should be light and agile, its subroutines connected like a string of pearls. The spirit and intent of the program should be retained throughout. There should be neither too little or too much, neither needless loops nor useless variables, neither lack of structure nor overwhelming rigidity." - The Tao of Programming, 4.1 - Geoffrey James My blog: Imperial Deltronics
| [reply] [d/l] [select] |
|
|
What if you just want to merge these two arrays:
...
my $data1 = [
{
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05',
'NUMBER' => '00001',
},
];
my $data2 = [
{
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b',
'CAR4' => '3d',
},
];
...
into:
my $data3 = [
{
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05',
'NUMBER' => '00001',
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b',
'CAR4' => '3d',
},
];
Thanks! | [reply] [d/l] [select] |
|
|
| [reply] |
|
|
Re: Combining two references
by locked_user sundialsvc4 (Abbot) on Jun 09, 2015 at 13:59 UTC
|
Whereas, I came up with a more pedantic solution, something like this:
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',
},
];
my $data2 = [
{
'CAR1' => '1',
'CAR2' => '2',
'CAR3' => '3',
},
{
'CAR1' => '1b',
'CAR2' => '2b',
'CAR3' => '3b',
},
];
my $i=0;
my @result;
foreach my $row1 (@$data1) {
my $record={};
while (my ($k1, $v1) = each(%$row1)) {$record->{$k1}=$v1};
my $row2=@$data2[$i];
while (my ($k2, $v2) = each(%$row2)) {$record->{$k2}=$v2};
push @result, $record;
$i++;
}
use Data::Dumper;
print Data::Dumper->Dump([\@result], ["result"]);
which gives:
$result = [
{
'CAR2' => '2',
'NAME' => 'PAUL DY',
'DATE' => '2009-05-05',
'CAR1' => '1',
'CAR3' => '3',
'NUMBER' => '00001'
},
{
'CAR2' => '2b',
'NAME' => 'ANTHONY RD',
'DATE' => '2012-01-07',
'CAR1' => '1b',
'CAR3' => '3b',
'NUMBER' => '00003'
}
];
I simply used a foreach loop to iterate over $data1, then used variable $i which is incremented within the loop to fetch the rows from $data2. I attempted to use consistent variable-names in both cases. I made no attempt to be clever nor efficient: I wanted the code to be “obvious.”
One thing to keep firmly in mind, when doing things like this, is that you can easily wind up manipulating references to things, within the output that you create ... the old FORTRAN EQUIVALENCE statement ... when you might need to be making “actual copies.” If you are moving or creating references, any change will be reflected in all references to that same thing, which might not be what you wanted nor expected.
| |
|
|
my $row2=@$data2[$i];
That way of accessing a single element of an array is usually discouraged unless you know what you're doing. Better is $data2->[$i].
| [reply] [d/l] [select] |