How do I print a hash structure in Perl?

2019-05-06 06:12发布

Examples:

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

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

How do I print the hash?

标签: perl hash
9条回答
劳资没心,怎么记你
2楼-- · 2019-05-06 06:29

The function printStruct below works using recursion and can print hashes of arrays, arrays of hashes or any mixture thereof to any depth. You call it with a reference to your structure, and a name of the structure in a string. The last input $pre is only used during the recursion to tell the initial entry into the recursive function. Just leave it blank when you call the function.

%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();
}

Result:

-----------------
%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

This function helped in a lot of programming and debugging of complex structures. I hope you guys find it as useful.

查看更多
劳资没心,怎么记你
3楼-- · 2019-05-06 06:32
printf ("%s = %s\n", $_, $hash {$_}) foreach (keys (%hash));
查看更多
冷血范
4楼-- · 2019-05-06 06:36

instead of

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

you should write

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

with the curly braces you get a REFERENCE to an anonymous hash, which is then stored as the first key of you %hash.

查看更多
虎瘦雄心在
5楼-- · 2019-05-06 06:39

Do you want to print the entire hash, or specific key, value pairs? And what is your desired result? IF it's just for debugging purposes, you can do something like:

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

You can use the each function if you don't care about ordering:

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

Or the for / foreach construct if you want to sort it:

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

Or if you want only certain values, you can use a hash slice, e.g.:

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

etc, etc. There is always more than one way to do it, though it helps to know what you're frying to do first :)

查看更多
够拽才男人
6楼-- · 2019-05-06 06:40

Syntax to access inner cells for your second example is like:

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

That will give you 1 in your example.

If you want to iterate on it, you can do it as follows (print lines are for illustration purposes):

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"
     }
}

Notice that things are a bit more tricky than necessary because the external $hash is a scalar reference to an anonymous hash. It would be simpler if it was a hash (i.e., like in my %hash = (1, 2); print $hash{1};).

(TIMTOWTDI: there is obviously more than one way to do it; I believe the above example is the simplest for me, but not the most efficient; using each instead of keys for iterating would avoid one unnecessary hash lookup).

查看更多
一纸荒年 Trace。
7楼-- · 2019-05-06 06:41
  while( my( $key, $value ) = each( %hash ) ) {
         ...
  }
查看更多
登录 后发表回答