可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
Now i am modifying the code a little
I am using the code for creating hash haivng duplicate keys. Its giving the syntax error.
use strict;
use warnings;
my $s = "12 A P1
23 B P5
24 C P2
15 D P1
06 E P5";
my $hash;
my @a = split(/\n/, $s);
foreach (@a)
{
my $c = (split)[2];
my $d = (split)[1];
my $e = (split)[0];
push(@{$hash->{$c}}, $d);
}
print Dumper($hash );
i am getting the output as
$VAR1 = {
'P5' => [
'B',
'E'
],
'P2' => [
'C'
],
'P1' => [
'A',
'D'
]
};
But i want the output like
$VAR1 = {
'P5' => {
'E' => '06',
'B' => '23'
},
'P2' => {
'C' => '24'
},
'P1' => {
'A' => '12',
'D' => '15'
}
};
How to do that
回答1:
Perl is telling you exactly what is wrong. You have used the strict
pragma, so using the %hash
variable without declaring it is a syntax error. While the string %hash
does not appear in your code, the string $hash{...}
does, on each of the problem lines. This is the syntax to access an element of the %hash
, which is why strict is complaining.
You have declared the variable $hash
, so accessing an element of the contained hash reference is written $$hash{...}
or $hash->{...}
. Fix the problem lines to access the correct variable and the code will compile.
回答2:
You hash declaration is incorrect, it should be:
my %hash = ();
or simply:
my %hash;
Then the rest of your code is both too complex and incorrect.
foreach (@a) {
my ($k, $v) = (split);
push @{$hash{$k}}, $v;
}
should be enough. See Autovivification for why this works.
With your code, the first time you see a key, you set $hash{$k}
to be a scalar. You can't then push
things to that key - it needs to be an array to begin with.
The if (-e $hash{$c})
test is wrong. -e
is a file existence test. If you want to know if a hash key exists, use:
if (exists $hash{$c}) { ... }
And print %hash;
won't do what you expect (and print %{$hash};
is invalid). You'll get a prettier display if you do:
use Data::Dumper;
print Dumper(\%hash);
(Great debugging too, this Data::Dumper
.)
回答3:
%hash
is a hash, and $hash
is a scalar (a hash reference, like \%hash
), they are two different variables
To refer to $hash
, to refer to the hash whose reference is stored in the scalar variable $hash
, you either have to use $hash->{$c}
or $$hash{$c}
See References quick reference
update:
#!/usr/bin/perl --
use strict; use warnings;
use Data::Dumper;
my $s = "P1 26
P5 23
P2 24
P1 15
P5 06 ";
my $hash = {};
for my $line ( split /[\r\n]+/, $s ) {
my( $c, $d ) = split ' ', $line;
push @{ $hash->{$c} }, $d;
}
print Dumper( $hash );
__END__
$VAR1 = {
'P5' => [
'23',
'06'
],
'P2' => [
'24'
],
'P1' => [
'26',
'15'
]
};
回答4:
See the working code, the fixed errors (comments in the code), and the resulting output:
use strict;
use warnings;
my $s = "P1 26
P5 23
P2 24
P1 15
P5 06 ";
my %hash; #my $hash ={};
#my $arr = [];
my @a = split(/\n/, $s);
foreach (@a)
{
my $d = (split)[1];
my $c = (split)[0];
push(@{$hash{$c}}, $d); #if ...
}
while (my ($key, $value) = each(%hash)) #print %{$hash};
{
print "$key @{$value}\n";
}
#Output:
#P5 23 06
#P2 24
#P1 26 15
回答5:
(Strange. Out of all the answers posted so far, none has actually answered the question...)
The code below produces the result asked for. The fundamental bit which seems to be missing from the original code is the two-level hash.
As an aside, there seems to be no reason for the outer hash to be a hashref and not a hash, so I made it a hash. Also you can pick out the split into variables in one line.
use strict;
use warnings;
use Data::Dumper;
my $s = "12 A P1
23 B P5
24 C P2
15 D P1
06 E P5";
my %hash;
my @a = split(/\n/, $s);
foreach (@a)
{
my ($e, $d, $c) = (split);
$hash{$c}{$d} = $e;
}
print Dumper(\%hash);