Beefy Boxes and Bandwidth Generously Provided by pair Networks
Don't ask to ask, just ask
 
PerlMonks  

iterate through a hash with two keys

by fionbarr (Pilgrim)
on Apr 29, 2013 at 17:32 UTC ( #1031265=perlquestion: print w/ replies, xml ) Need Help??
fionbarr has asked for the wisdom of the Perl Monks concerning the following question:

hi...I have a hash that looks like:
$hash{'a' .. 'h'}{$label} = $value;
I want to iterate through the 'a' ..'h' and print all the values keyed by $label

Comment on iterate through a hash with two keys
Download Code
Re: iterate through a hash with two keys
by MidLifeXis (Monsignor) on Apr 29, 2013 at 17:34 UTC

    What you are doing is trying to assign a value, but not correctly. To assign $value, you could do something like this...

    $hash{$_}{$label} = $value for 'a' .. 'h';
    To print the value, use print, printf, or say with the same type of a structure.

    --MidLifeXis

      I am using xml_writer and I want to do this: for ('a' .. 'c') { $xml_writer->dataElement("LastName" => $t{A}{LastName}); } where the hash was filled by $t{A}{LastName} = "Smith"

      Independent of your solution to fionbarr's question and his real intention, I have tried to correct his code in the following way:

      use strict; use warnings; my %hash; my $label = "label"; my $value = "value"; # this does not work !!! @hash{ 'a'..'h' } = ( { $label => $value } ) x 9; $hash{ 'a' }{ $label } = "newvalue"; print $hash{ 'b' }{ $label },"\n"; # is "newvalue" !!!

      This results in a structure where $hash{'a'} to $hash{'h'} all point to the same hash, so changing one changes all of them.

      Is there a way to have the x operator really create 9 independent hash refs? (If this is helpful here or not is a different question.)

      The following code works but is too cumbersome.

      use strict; use warnings; my %hash; my $label = "label"; my $value = "value"; # this works !!! @hash{ 'a'..'h' } = ( { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, { $label => $value }, ); $hash{ 'a' }{ $label } = "newvalue"; print $hash{ 'b' }{ $label },"\n"; # is "value" !!!

        map { { $label => $value } } 1 .. 9?

        What you are doing is creating the hashref, and duplicating the same hashref that number of times.

        --MidLifeXis

Re: iterate through a hash with two keys
by LanX (Canon) on Apr 29, 2013 at 17:36 UTC
    Not sure what you want ...

    ... if $label should be variable, try

     print $hash{$_}{$label} for keys %hash

    Update:

    or shorter

     print $_->{$label} for values %hash

    Cheers Rolf

    ( addicted to the Perl Programming Language)

    errata

    s/values/keys/ in first expression

      I didn't ask the question properly. I want to print all the labels and values for each of 'a' .. 'h' the label is a variable. I am filling this hash like: $hash{a}{$label} = $value; where $label is a text string.
        > I didn't ask the question properly.

        indeed!

        > I want to print all the labels and values for each of a .. h

        DB<103> @hash{$_} = {x=>$x++,y=>$x++} for a..h => "" DB<112> while ( my ($k1,$v1) = each %hash ) { while ( my ($k2,$v2) = each %$v1 ) { print "$k1 - $k2 -$v2\n" } } e - y -25 e - x -24 a - y -17 a - x -16 d - y -23 d - x -22 ... # and so on

        But are you looking for Data::Dumper ?

        UPDATE

        DB<106> print Dumper \%hash $VAR1 = { 'e' => { 'y' => 9, 'x' => 8 }, 'a' => { 'y' => 1, 'x' => 0 }, 'd' => { 'y' => 7, 'x' => 6 }, 'c' => { 'y' => 5, 'x' => 4 }, ...

        FWIW I prefer Data::Dump or YAML, but Data::Dumper is core.

        Cheers Rolf

        ( addicted to the Perl Programming Language)

        ) interesting Module::Build::YAML was first released with perl 5.009004

        UPDATE YAML
        DB<106> use YAML::Tiny => 0 DB<107> Dump(\%hash) --- a: x: 16 y: 17 b: x: 18 y: 19 c: x: 20 y: 21 d: x: 22 y: 23 ...
        This may be what you want.
        use strict; use warnings; my $label1 = 'L1'; my $label2 = 'L2'; my %hash; @hash{'a' .. 'h'} = ( {$label1 => 1 }, {$label1 => 2 }, {$label2 => 3 }, {$label1 => 4 }, {$label2 => 5 }, {$label1 => 6 }, {$label2 => 7 }, {$label1 => 8 }, ); while ( my( $key,$subhash ) = each %hash) { print "$key: $subhash->{$label1}\n" if exists $subhash->{$label1}; }
        OUTPUT:
        a: 1 d: 4 h: 8 b: 2 f: 6
        Bill

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1031265]
Approved by moritz
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others chilling in the Monastery: (5)
As of 2015-07-04 05:09 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    The top three priorities of my open tasks are (in descending order of likelihood to be worked on) ...









    Results (57 votes), past polls