tags:

views:

168

answers:

6

I have a $map{k1}{k2}{k3}{k4}.

How can I write the loop correctly to print all values? The following does not work.

for my $k1 (sort keys %tripletsCountMap) {
    for my $k2 (sort keys %$tripletsCountMap{k1}){
     for my $k3 (sort keys %$tripletsCountMap{k1}{k2}) {
      for my $k4 (sort keys %$tripletsCountMap{k1}{k3}{k3}){
       print "$k1 $k2 $k3 $k4\n";
      }
     }
    }
}
A: 

You're printing all the keys but not the final value.

In the most inner loop add:


my $val = $map{$k1}{$k2}{$k3}{$k4};
print "$val\n"; 
PP
Actually nothing is printed. In my code at least $1 ... $4 must be printed right, even though the value is not printed.
ajay
Have you added `use strict;` to the top of your program?
PP
@ajay: There is a difference between **`$1`** and **`$k1`** and **`k1`**.
Sinan Ünür
+10  A: 

Note that there is a difference between k1 and $k1.

for my $k1 (sort keys %tripletsCountMap) {
    for my $k2 (sort keys %{ $tripletsCountMap{$k1} }){
        for my $k3 (sort keys %{ $tripletsCountMap{$k1}{$k2} }) {
            for my $k4 (sort keys %{ $tripletsCountMap{$k1}{$k2}{$k3} }){
                printf "$k1 $k2 $k3 $k4: $tripletsCountMap{$k1}{$k2}{$k3}{$k4}\n";
            }
        }
    }
}

Better yet:

use Data::Dumper;
print Dumper \%tripletsCountMap;

And, why are you sorting the keys? I understand the point @ysth in the comments below. I am just not in the habit of sorting the keys of a hash when I iterate over them unless there is some explicit output related requirement.

Sinan Ünür
+1 for data::dumper
ennuikiller
unless there are huge performance implications (usually not the case), looping over sorted keys is a very good idea. it frees you from a whole class of perl version/platform/data dependent bugs where the loop body somehow depends on one key being processed before another.
ysth
Sorting (extra-work) to remove a possible user-dependency that was /never/ supported sounds silly. I would suggest removing the sort if this was your logic.
Evan Carroll
+4  A: 

If this is for debugging or similar purposes, it's probably better to use Data::Dumper to do this sort of thing. It's intelligent enough to follow through the data structure and get it right.

gorilla
+4  A: 

When using % to dereference an expression, the expression must be enclosed in {} unless it's a simple scalar (e.g. %$href).

I recommend you read http://perlmonks.org/?node=References+quick+reference.

ysth
+1  A: 

$k1 is the variable, k1 is a bareword.

perl -e '%h = (1 => 2, "k1" => 3); $k1 = 1; printf "%d %d\n", $h{$k1}, $h{k1}'

2 3

Then if you use hash reference be cautious to use scalar variables to store them.

perl -e '$h = {1 => 2, "k1" => 3}; $k1 = 1; printf "%d %d\n", $h->{$k1}, $h->{k1}'

2 3

If you happened to write something like nothing will work as expected:

perl -e '%h = {1 => 2, "k1" => 3}; $k1 = 1; printf "%d %d\n", $h->{$k1}, $h->{k1}'

0 0

If the bareword is not the problem (it probably is), then you should carefully check how you built your map.

kriss
A: 

Poor man's Dumper:

sub trace {
    my ( $val, $path ) = @_;
    my $ref = ref $val;
    if ( $ref eq '' ) {
     print "$path = $val\n";
    }
    elsif ( $ref eq 'HASH' ) {
     trace( $val->{$_}, $path . "{$_}" ) for keys %$val;
    }
    elsif ( $ref eq 'ARRAY' ) {
     trace( $val->[$_], $path . "[$_]" ) for 0 .. $#$val;
    }
    else {
     warn "I don't know what to do with $ref at $path\n";
    }
}

trace($map, '$map->');
Hynek -Pichi- Vychodil