How to create hash with duplicate keys

∥☆過路亽.° 提交于 2019-12-26 08:15:23

问题


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


来源:https://stackoverflow.com/questions/8613452/how-to-create-hash-with-duplicate-keys

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!