我目前正在学习Perl。我有Perl哈希,其中包含对哈希和数组的引用。哈希和数组可能进而包含对其他哈希/数组的引用。

我编写了一个子例程来递归解析哈希,并使用适当的缩进打印它们。尽管该例程可以按预期工作,但我的讲师对以下代码的可读性和优雅程度并不满意。

我非常感谢Perl专家对以下代码的可能优化发表意见。

这是我完整的代码段。

# 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]:乔治
arrayofArrays [1]:jane
arrayofArrays [2]:elroy
arrayofArrays [2]:
arrayofArrays [0]:homer
arrayofArrays [1]:marge
arrayofArrays [2]:bart

arrayofHash == ARRAY(0x9d9bba8)
--------------------------------------------
arrayofHash [0]:
丈夫==巴尼
儿子== bamm bamm
妻子==贝蒂
arrayofHash [1]:
丈夫==乔治
儿子==艾洛伊
妻子==简

hashofHash == HASH(0x9da45f8)
--------------------------------------------

打火石== HASH(0x9d9bb48)
丈夫==弗雷德
friend ==巴尼

jetsons ==哈希(0x9d9bbf8)
他的男孩==艾洛伊
丈夫==乔治
妻子==简

辛普森== HASH(0x9d9bc48)
丈夫==荷马
小子==巴特
妻子==玛格

最佳答案

  • 始终使用use strict;
  • 要成为一个好 child ,也请使用use warnings
  • 用于子例程的名称应该使子例程的作用显而易见。 “recurseErrors”违反了该原则。是的,它确实会递归。但是有什么错误呢?
  • 在每个子例程的第一行,您应该声明并初始化任何参数。 recurseErrors首先声明$ str,然后声明其参数。
  • 不要像在str()中那样混合使用shift和= @_
  • 您可能会考虑将现在称为recurseErrors的内容分解为用于处理数组和哈希的专用例程。
  • 无需像在第99行和第109行一样对变量进行引用。

  • 除此之外,我认为您的老师那天过得很糟糕。

    关于perl - 在Perl中递归打印数据结构,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/1038271/

    10-10 02:56