I am currently learning Perl. I have Perl hash that contains references to hashes and arrays. The hashes and arrays may in turn contain references to other hashes/arrays.
I wrote a subroutine to parse the hash recursively and print them with proper indentation. Though the routine works as expected, my instructor was not convinced about the readability and elegance of the below code.
I would really appreciate to get the views of Perl experts here on possible optimization of the below code.
Here is my complete code snippet..
# Array of Arrays
$ref_to_AoA = [
[ "fred", "barney" ],
[ "george", "jane", "elroy" ],
[ "homer", "marge", "bart" ],
];
#Array of Hashes
$ref_to_AoH = [
{
husband => "barney",
wife => "betty",
son => "bamm bamm",
},
{
husband => "george",
wife => "jane",
son => "elroy",
},
];
# Hash of Hashes
$ref_to_HoH = {
flintstones => {
husband => "fred",
pal => "barney",
},
jetsons => {
husband => "george",
wife => "jane",
"his boy" => "elroy", # Key quotes needed.
},
simpsons => {
husband => "homer",
wife => "marge",
kid => "bart",
},
};
# Hash which contains references to arrays and hashes
$finalHash = {
'arrayofArrays' => $ref_to_AoA,
'arrayofHash' => $ref_to_AoH,
'hashofHash' => $ref_to_HoH,
};
$string = str($finalHash);
print "$string\n";
#------------------------------------------------------------------
sub str {
my $hash = shift;
my ($space, $newline, $delimiter) = @_;
$space = "" unless (defined $space);
$newline = "\n\n\n" unless (defined $newline);
$delimiter = "\n--------------------------------------------" unless (defined $delimiter);
my $str = "";
for (sort keys %{$hash}) {
my $value = $hash->{$_};
$str .= "$newline$space$_ == $value$delimiter";
$str .= recurseErrors($value,$space);
}
$str;
}
#------------------------------------------------------------------
sub recurseErrors {
my $str;
my ($value,$space) = @_;
my $ref = ref $value;
if ($ref eq 'ARRAY') {
my $i = 0;
my $isEmpty = 1;
my @array = @$value;
$space .= "\t";
for my $a (@array) {
if (defined $a) {
$isEmpty = 0;
$str .= "\n$space$_\[$i\] :";
$str .= recurseErrors($a,$space);
}
$i++;
}
$str .= "= { }" if ($isEmpty);
} elsif ($ref eq 'HASH') {
$space .= "\t";
for my $k (sort keys %$value) {
if ( ( ref($value->{$k}) eq 'HASH') || (ref $value->{$k} eq 'ARRAY') ) {
my $val = $value->{$k};
$str .= "\n\n$space$k == ";
$str .= "$val";
}
else {
$str .= "\n$space$k == ";
}
$str .= recurseErrors($value->{$k},$space);
}
# we have reached a scalar (leaf)
} elsif ($ref eq '') {
$str .= "$value";
}
$str
}
#------------------------------------------------------------------
arrayofArrays == ARRAY(0x9d9baf8)
--------------------------------------------
arrayofArrays[0] :
arrayofArrays[0] :fred
arrayofArrays[1] :barney
arrayofArrays[1] :
arrayofArrays[0] :george
arrayofArrays[1] :jane
arrayofArrays[2] :elroy
arrayofArrays[2] :
arrayofArrays[0] :homer
arrayofArrays[1] :marge
arrayofArrays[2] :bart
arrayofHash == ARRAY(0x9d9bba8)
--------------------------------------------
arrayofHash[0] :
husband == barney
son == bamm bamm
wife == betty
arrayofHash[1] :
husband == george
son == elroy
wife == jane
hashofHash == HASH(0x9da45f8)
--------------------------------------------
flintstones == HASH(0x9d9bb48)
husband == fred
pal == barney
jetsons == HASH(0x9d9bbf8)
his boy == elroy
husband == george
wife == jane
simpsons == HASH(0x9d9bc48)
husband == homer
kid == bart
wife == marge
use strict;use warnings as well.Apart from that I think your instructor had a bad day that day.
maybe Data::Dumper is what you want:
use Data::Dumper;
$str = Dumper($foo);
print($str);
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With