【问题标题】:How do I print a hash structure in Perl?如何在 Perl 中打印哈希结构?
【发布时间】:2011-01-26 17:24:31
【问题描述】:

例子:

%hash = (2010 => 21, 2009=> 9);

$hash = {
    a => {
        0 => {test => 1},
        1 => {test => 2},
        2 => {test => 3},
        3 => {test => 4},
    },
};

如何打印哈希?

【问题讨论】:

标签: perl hash


【解决方案1】:

您想打印整个散列,还是特定的键、值对?你想要的结果是什么?如果只是出于调试目的,您可以执行以下操作:

use Data::Dumper;
print Dumper %hash; # or \%hash to encapsulate it as a single hashref entity;

如果您不关心订购,可以使用each 函数:

while ( my($key, $value) = each %hash ) {
    print "$key = $value\n";
}

如果你想对它进行排序,也可以使用 for / foreach 构造:

for my $key ( sort keys %hash ) {
    print "$key = $hash{$key}\n";
}

或者如果你只想要某些值,你可以使用哈希切片,例如:

print "@hash{qw{2009 2010}}\n";

等等等等。总是有不止一种方法可以做到这一点,尽管首先知道你要做什么会有所帮助:)

【讨论】:

  • 我可能是错的,但我相信 OP 哈希问题是访问项目的语法甚至使用哈希引用进行哈希,而不是哈希上的迭代器。请注意,在他的第二个示例中,他的变量是标量 $hash,而不是散列。
  • @kriss:最初的问题询问如何打印哈希,看来 OP 已经用另一个示例编辑了该问题。使用 Data::Dumper 的第一个示例仍然可以正确处理。
  • @Duncan:Data::Dumper 无处不在。另一方面,不仅仅是打印数据;-)
  • @kriss:打印散列比打印数据还多?问题是“如何在 Perl 中打印哈希结构?” :)
【解决方案2】:
  while( my( $key, $value ) = each( %hash ) ) {
         ...
  }

【讨论】:

    【解决方案3】:

    而不是

    %hash = { 2010=> 21, 2009=> 9 }
    

    你应该写

    %hash = ( 2010=> 21, 2009=> 9 ); 
    

    使用花括号,您可以获得对匿名哈希的引用, 然后将其存储为您的第一个密钥 %hash。

    【讨论】:

    • 更糟糕的是,它以字符串形式存储!
    • 是的,但是在他的 second 示例中,OP 写道: $h = { some content };并且 that 可能是合法的(比如将哈希引用传递给 sub)。 (即使你可能是对的而且这是一个新手错误)。
    【解决方案4】:

    第二个示例访问内部单元格的语法如下:

    print $hash->{"a"}{0}{"test"}
    

    这将在您的示例中为您提供 1。

    如果要对其进行迭代,可以按如下方式进行(打印线用于说明目的):

    my $hash = {"a"=>{ 0=>{"test"=>1}, 1=>{"test"=>2}, 2=>{"test"=>3}, 3=>{"test"=>4} } };
    print "Direct access to item : ".$hash->{"a"}{1}{"test"}."\n";
    
    foreach my $k1 (keys(%$hash)) {
        print "keys of level 1: $k1\n";
        foreach my $k2 (keys(%{$hash->{$k1}})) {
            print "keys of level 2: $k2\n";
            print "values: ".$hash->{$k1}{$k2}{"test"}."\n"
         }
    }
    

    请注意,由于外部 $hash 是对匿名哈希的标量引用,因此事情比必要的要复杂一些。如果它是一个哈希值会更简单(例如,像my %hash = (1, 2); print $hash{1};)。

    (TIMTOWTDI:显然有不止一种方法可以做到;我相信上面的例子对我来说是最简单的,但不是最有效的;使用each而不是keys for 迭代将避免一次不必要的哈希查找)。

    【讨论】:

    • 大多数程序员不写双印记和重复箭头。这个符号更具可读性:$hash->{'a'}{0}{'test'}
    • @daxim:是的,我试图让它对初学者更明确,但我可能在这方面失败了。我会改的。
    • 现阶段递归可能太高级了?
    • @Duncan:可能,但我真的不知道你想在那个问题中将递归放在哪里?有关如何使用哈希制作树或图的一些示例?
    【解决方案5】:

    你可以试试这个,

    while(my ($key,$val)=each %HASH){
    print $key," = ",$val,"\n";
    while(my ($kkey,$vval)=each %{$HASH{$key}}){
    print "   ",$kkey," = ",$vval,"\n";
    }
    }
    

    【讨论】:

    • 你试过了吗?第一次打印的结果是什么:print $key," = ",$val,"\n";
    【解决方案6】:

    使用keys , values函数

    @keys = keys %hash ; 
    
    @values = values %hash 
    

    【讨论】:

      【解决方案7】:

      这应该会有所帮助:

      foreach $key (keys %hash)
      {
        print "key is : $key, value is : $hash{$key}\n";
      }
      

      干杯

      【讨论】:

      • 感谢您的回复,如果我的哈希是这样的 $hash = {'a'=>{ 0=>{'test'=>'1'}, 1=>{'test'=> '2'}, 2=>{'test'=>'3'}, 3=>{'test'=>'4'} } };那我该怎么办
      【解决方案8】:
      printf ("%s = %s\n", $_, $hash {$_}) foreach (keys (%hash));
      

      【讨论】:

        【解决方案9】:

        下面的函数 printStruct 使用递归工作,可以将数组的哈希值、哈希数组或其任何混合打印到任何深度。您可以通过引用您的结构和字符串中的结构名称来调用它。最后一个输入 $pre 仅在递归期间用于告诉递归函数的初始入口。调用函数时将其留空即可。

        %hash = (2010 => 21, 2009=> 9);
        printStruct(\%hash,"\%hash");
        
        $hash = {
            a => {
                0 => {test => 1},
                1 => {test => 2},
                2 => {test => 3},
                3 => {test => 4},
            },
        };
        $hash->{b}=[1..5];
        printStruct($hash,"\$hash");
        my @array=[apple,banana,orange,$hash];
        printStruct(\@array,"\@array");
        
        sub printStruct {
            my ($struct,$structName,$pre)=@_;
            print "-----------------\n" unless (defined($pre));
            if (!ref($struct)){ # $struct is a scalar.
            print "$structName=$struct\n";
            } elsif (ref($struct) eq "ARRAY") { # Struct is an array reference
            return ("ARRAY(".scalar(@$struct).")") if (@$struct>100);
            for(my$i=0;$i<@$struct;$i++) {
                if (ref($struct->[$i]) eq "HASH") {
                printStruct($struct->[$i],$structName."->[$i]",$pre." ");
                } elsif (ref($struct->[$i]) eq "ARRAY") { # contents of struct is array ref
                print "$structName->"."[$i]=()\n" if (@{$struct->[$i]}==0);
                my $string = printStruct($struct->[$i],$structName."->[$i]",$pre." ");
                print "$structName->"."[$i]=$string\n" if ($string);
                } else { # contents of struct is a scalar, just print it.
                print "$structName->"."[$i]=$struct->[$i]\n";
                }
            }
            return();
            } else { # $struct is a hash reference or a scalar
            foreach (sort keys %{$struct}) {
                if (ref($struct->{$_}) eq "HASH") {
                printStruct($struct->{$_},$structName."->{$_}",$pre." ");
                } elsif (ref($struct->{$_}) eq "ARRAY") { # contents of struct is array ref
                my $string = printStruct($struct->{$_},$structName."->{$_}",$pre." ");
                print "$structName->"."{$_}=$string\n" if ($string);
                } else { # contents of struct is a scalar, just print it.
                print "$structName->"."{$_}=$struct->{$_}\n";
                }
            }
            return();
            } 
            print "------------------\n" unless (defined($pre));
            return();
        }
        

        结果:

        -----------------
        %hash->{2009}=9
        %hash->{2010}=21
        -----------------
        $hash->{a}->{0}->{test}=1
        $hash->{a}->{1}->{test}=2
        $hash->{a}->{2}->{test}=3
        $hash->{a}->{3}->{test}=4
        $hash->{b}->[0]=1
        $hash->{b}->[1]=2
        $hash->{b}->[2]=3
        $hash->{b}->[3]=4
        $hash->{b}->[4]=5
        -----------------
        @array->[0]->[0]=apple
        @array->[0]->[1]=banana
        @array->[0]->[2]=orange
        @array->[0]->[3]->{a}->{0}->{test}=1
        @array->[0]->[3]->{a}->{1}->{test}=2
        @array->[0]->[3]->{a}->{2}->{test}=3
        @array->[0]->[3]->{a}->{3}->{test}=4
        @array->[0]->[3]->{b}->[0]=1
        @array->[0]->[3]->{b}->[1]=2
        @array->[0]->[3]->{b}->[2]=3
        @array->[0]->[3]->{b}->[3]=4
        @array->[0]->[3]->{b}->[4]=5
        

        此功能有助于对复杂结构进行大量编程和调试。我希望你们觉得它很有用。

        【讨论】:

          猜你喜欢
          • 2023-03-08
          • 2012-10-23
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-09-30
          • 2016-12-18
          • 1970-01-01
          • 2011-10-27
          相关资源
          最近更新 更多