David92 has asked for the wisdom of the Perl Monks concerning the following question:

Hey guys,

My problem occurs when I want to fill my matrix / array. I have a HASH that contains some values:

%elohimHash{$folderId}{$customer}{$version}{points} = $totPoints;

I want to draw a Pie Chart using Google charts, so I need to create an HTML. This is not important part, as this is already done.

My problem is to fill my array in a the way as it is described at the bottom of this question.

Check the code:

foreach $folderId (keys %elohimHash){ foreach $customer (keys %{$elohimHash{$folderId}}){ foreach $version (keys %{$elohimHash{$folderId}{$customer}}){ $totSP = $elohimHash{$folderId}{$customer}{$version}{totSP}; @valueArray = ([$version,$totSP]); }}}
What I'd like to get is a Pie chart that will display all the version with their POINTS.

So my array should look like: @valueArray = ([version1, points1],[ version2,points2],[version3,points3]); etc. depending how many versions are there in Hash.

Any ideas?

Replies are listed 'Best First'.
Re: Filling a matrix
by Athanasius (Archbishop) on Aug 08, 2014 at 12:20 UTC

    Hello David92,

    The main problem is this line:

    @valueArray = ([$version,$totSP]);

    which simply overwrites the whole array on each iteration of the innermost loop. Replace it with this:

    push @valueArray, [$version, $totSP];

    Also, please put

    use strict; use warnings;

    at the head of your script, and declare all variables explicitly as lexicals by using my:

    for my $folderId (keys %hash) { for my $customer (keys %{$hash{$folderId}}) { for my $version (keys %{$hash{$folderId}{$customer}}) { my $totSP = $hash{$folderId}{$customer}{$version}{totSP}; push @valueArray, [$version, $totSP]; } } }

    — and note how much easier it is to read code which is indented consistently. ;-)

    Hope that helps,

    Athanasius <°(((><contra mundum Iustus alius egestas vitae, eros Piratica,

Re: Filling a matrix
by Random_Walk (Prior) on Aug 08, 2014 at 15:17 UTC

    I think Google chart may want JSON formatted data, so do have a look at the Perl JSON module. Its simple and fast. Otherwise you will be re-inventing wheels. Before that of course, you will need your data in something like the correct format. I guess you need an array of arrays...

    # untested code use strict; use warnings; use Data::Dumper; use JSON; # read up on this, it may be a great help my $json = JSON->new->allow_nonref; my %elohimHash; # Not sure where this comes from, but obviously it mus +t be defined by here... my @ValsArray; for my $folderId (keys %elohimHash){ for my $customer (keys %{$elohimHash{$folderId}}){ for my $version (keys %{$elohimHash{$folderId}{$customer}}){ my $totSP = $elohimHash{$folderId}{$customer}{$version}{totSP +}; push @valsArray, [$version,$totSP]; } } } print Dumper \@ValsArray; print "-" x 30; print "\n"; print $json->encode(\@ValsArray);

    Cheers,
    R.

    Pereant, qui ante nos nostra dixerunt!
      my %elohimHash; # Not sure where this comes from, but obviously it mus +t be defined by here...
      Probably not. It appears that the hash has been populated before, since it is being read in order to populate the @valsArray array of arrays.
Re: Filling a matrix
by Anonymous Monk on Aug 08, 2014 at 12:04 UTC
      I edited it a bit. The point of my question is not how to create a Pie Chart,but simply how to to push in the values in correct order, inside my Matrix / Array.

        A clearer picture of the input data and desired output data would be helpful, e.g. use Data::Dumper; print Dumper(\%elohimHash); (possibly reduced to some small number of example datasets), since at the moment your post does not agree with itself ("%elohimHash{$folderId}{$customer}{$version}{points} = $totPoints;" vs. "$totSP = $elohimHash{$folderId}{$customer}{$version}{totSP};") As for the output, is @valueArray supposed to be filled per $customer, per $folderId, or across the entire input hash?

Re: Filling a matrix
by bulrush (Scribe) on Aug 09, 2014 at 11:49 UTC
    $totSP = $elohimHash{$folderId}{$customer}{$version}{totSP};

    Isn't the {totSP} on the end an error? Shouldn't it be {$totSP}?

    Does Perl even support a hash 4 levels deep? What is the limit on that anyway?

    Perl 5.8.8 on Redhat Linux RHEL 5.5.56 (64-bit)

      Does Perl even support a hash 4 levels deep? What is the limit on that anyway?

      Since multilevel hashes are really just hashes holding references to other (anonymous) hashes, I don't think there is any real limit. Try e.g. the following:

      #!/usr/bin/perl use strict; use warnings; use feature qw/say/; use Data::Dumper; my %hash = (); my $hashref = \%hash; for(1..255) { $hashref = $hashref->{$_} = {}; } print Dumper \%hash;

      This works like a charm and as expected.

      Bisecting this, I found I can go up to 4028 layers of indirection before Perl segfaults at 4029. (And 4028 produces 178 MiB of output from Data::Dumper.)

        Without the print call, there's no problem running it millions deep. What you have is a torture test for the Data::Dumper.

        Also try with $Data::Dumper::Indent = 0; though it still segfaults.