在Perl中递归打印数据结构 [英] Recursively printing data structures in Perl
问题描述
我目前正在学习Perl.我有Perl哈希,其中包含对哈希和数组的引用.哈希和数组可能进而包含对其他哈希/数组的引用.
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.
我非常感谢Perl专家对以下代码的可能优化发表看法.
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
. - 用于子例程的名称应该使子例程的作用显而易见. "recurseErrors"违反了该原则.是的,它确实会递归.但是有什么错误?
- 在每个子例程的第一行,您应声明并初始化任何参数. recurseErrors首先声明$ str,然后声明其参数.
- 不要像在str()中那样混合使用shift和= @_
- 您可以考虑将现在称为recurseErrors的对象分解为用于处理数组和哈希的专用例程.
- 无需像在99行和109行那样对变量进行引用.
- Always use
use strict
; - To be a good boy, use
use warnings
as well. - The names you use for subroutines should make it obvious what the subroutine does. "recurseErrors" kind of violates that principle. Yes, it does recurse. But what errors?
- On the first line of each subroutine you should declare and initialize any parameters. recurseErrors first declares $str and then declares its parameters.
- Don't mix shift and = @_ like you do in str()
- You might consider breaking up what is now called recurseErrors into specialized routines for handling arrays and hashes.
- There's no need to quote variables like you do on lines 99 and 109.
除此之外,我认为您的讲师那天过得很糟糕.
Apart from that I think your instructor had a bad day that day.
这篇关于在Perl中递归打印数据结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!