如何打印作为%散列值的@array的$元素?

时间:2022-09-20 21:43:12

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).

我认为这对于有经验的人来说应该是很容易解决的,虽然我在谷歌上搜索过,但是找不到适合我的东西。我只是想让$amountok和$amountko给出索引0和1的值,但它不是这样工作的(参见# 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

这将给出一个错误:“不能使用字符串”7作为数组ref。这一定是可能的,但我就是不知道怎么做!谢谢你们

this is the Dumper output of %elementhash:

这是%elementhash的倾倒输出:

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

1 个解决方案

#1


5  

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.

哈希元素包含数组引用。即使数组ref中只有一个值,它仍然是一个数组ref。您可以使用->操作符来取消引用。

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

Note that you first have a hash, not a hash reference, so there is no arrow before the {$key} part. Inside there is an array reference. In fact, you don't strictly need to put a -> in front of the [0] because Perl knows that nested data structures are built from references. It's a matter of preference that's been well discussed. I personally like the arrow, but it's not needed here1.

注意,您首先有一个散列,而不是一个散列引用,因此在{$key}部分之前没有箭头。里面有一个数组引用。实际上,您并不需要在[0]前面加上->,因为Perl知道嵌套数据结构是由引用构建的。这是一个已经被充分讨论过的偏好问题。我个人喜欢这支箭,但这里不需要。

What you tried to do with @{$elementhash{$key}[0]} was take the first element inside the $key, e. g. the 7 for key 1000, and deref that as an array. Of course you can't do that, because it's a number, and not an array reference.

您尝试使用@{$elementhash{$ $key}[0]}所做的是获取$key中的第一个元素,例如,7表示key 1000, deref表示数组。当然你不能这么做,因为它是一个数字,而不是一个数组引用。

Because not all of the arrays in your data structure 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.

因为不是数据结构中的所有数组都有两个值,所以应该检查第二个值是否存在。您可以使用//定义或操作符来实现这一点。它允许0或其他非真值,但不允许undef。

Finally, you were missing a my for $valueofkey.

最后,你错过了$valueofkey的一个my。

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.

注意,可以重写最后一行以使用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".

如果您的Perl至少是5.10版本,那么您还可以打开use特性‘say’,这样就不需要打印“\n”了。

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

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

如果您有更复杂的CSV,可以考虑使用Text::CSV或Text:::CSV_XS。


1) You do need one arrow if the variable that you are starting from is a reference. But you can omit the following ones.

1)如果开始的变量是引用,则需要一个箭头。但是你可以省略下面的。

my $foo = { bar => [1, 2, 3] };
say $foo->{bar}[2]; # works
say $foo{bar}[2]; # complains that %foo needs explicit package name

#1


5  

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.

哈希元素包含数组引用。即使数组ref中只有一个值,它仍然是一个数组ref。您可以使用->操作符来取消引用。

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

Note that you first have a hash, not a hash reference, so there is no arrow before the {$key} part. Inside there is an array reference. In fact, you don't strictly need to put a -> in front of the [0] because Perl knows that nested data structures are built from references. It's a matter of preference that's been well discussed. I personally like the arrow, but it's not needed here1.

注意,您首先有一个散列,而不是一个散列引用,因此在{$key}部分之前没有箭头。里面有一个数组引用。实际上,您并不需要在[0]前面加上->,因为Perl知道嵌套数据结构是由引用构建的。这是一个已经被充分讨论过的偏好问题。我个人喜欢这支箭,但这里不需要。

What you tried to do with @{$elementhash{$key}[0]} was take the first element inside the $key, e. g. the 7 for key 1000, and deref that as an array. Of course you can't do that, because it's a number, and not an array reference.

您尝试使用@{$elementhash{$ $key}[0]}所做的是获取$key中的第一个元素,例如,7表示key 1000, deref表示数组。当然你不能这么做,因为它是一个数字,而不是一个数组引用。

Because not all of the arrays in your data structure 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.

因为不是数据结构中的所有数组都有两个值,所以应该检查第二个值是否存在。您可以使用//定义或操作符来实现这一点。它允许0或其他非真值,但不允许undef。

Finally, you were missing a my for $valueofkey.

最后,你错过了$valueofkey的一个my。

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.

注意,可以重写最后一行以使用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".

如果您的Perl至少是5.10版本,那么您还可以打开use特性‘say’,这样就不需要打印“\n”了。

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

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

如果您有更复杂的CSV,可以考虑使用Text::CSV或Text:::CSV_XS。


1) You do need one arrow if the variable that you are starting from is a reference. But you can omit the following ones.

1)如果开始的变量是引用,则需要一个箭头。但是你可以省略下面的。

my $foo = { bar => [1, 2, 3] };
say $foo->{bar}[2]; # works
say $foo{bar}[2]; # complains that %foo needs explicit package name