Zesa Rex Zesa Rex - 1 month ago 7
Perl Question

How to print an $element of an @array that is used as a value of %hash?

I think this should be easy to solve for experienced people, for me though I was trying and searched on google about this but couldnt find anything that fits my situation. I just want to let $amountok and $amountko give out the values they have at index 0 and 1 but it is not working like this (see # marks).

print ERGEBNIS "ID;Amount;Amount OK;Amount KO\n";
foreach my $key (keys %elementhash){
my $sum = 0;
foreach $valueofkey(@{$elementhash{$key}}){
$sum += $valueofkey;
}

#my $amountok= @{$elementhash{$key}[0]};
#my $amountko= @{$elementhash{$key}[1]};

print ERGEBNIS $key.";".$sum.";".$amountok.";".$amountko."\n";

}


this would give me out the error: "Cant use string "7" as an array ref.", this must be possible somehow but i just don't know how! thank you guys

this is the Dumper output of %elementhash:

$VAR1 = { '1000' => [7],
'2000' => [5],
'3000' => [56, 12]
};

Answer

Your hash elements contain array references. Even if there is only one value in the array ref, it's still an array ref. You can use the -> operator for dereferencing.

$elementhash{$key}->[0];

Note that you first have a hash, not a hash reference, so there is no arrow before the {$key} part. But inside there is an array reference, so you need a ->[0].

Because not all of the arrays have two values, you should check if the second value exists. You can do that with the // defined-or operator. It allows 0 or other un-true values, but not undef.

Finally, you were missing a my for $valueofkey.

use strict;
use warnings;

my %elementhash = (
    '1000' => [7],
    '2000' => [5],
    '3000' => [ 56, 12 ]
);

print "ID;Amount;Amount OK;Amount KO\n";
foreach my $key ( keys %elementhash ) {
    my $sum = 0;
    foreach my $valueofkey ( @{ $elementhash{$key} } ) {
        $sum += $valueofkey;
    }

    my $amountok = $elementhash{$key}->[0];
    my $amountko = $elementhash{$key}->[1] // 0;

    print $key. ";" . $sum . ";" . $amountok . ";" . $amountko . "\n";
}

Note that you can rewrite the last line to use join.

print join( ';', $key, $sum, $amountok, $amountko ),  "\n";

If your Perl is at least version 5.10, you can also turn on use feature 'say' so you don't need to print the "\n".

say join ';', $key, $sum, $amountok, $amountko;

If you have more complicated CSV, consider using Text::CSV or Text::CSV_XS instead.

Comments