How to create hash of array in Perl
I have a data like this
Group AT1G01040-TAIR-G
LOC_Os03g02970 69%
Group AT1G01050-TAIR-G
LOC_Os10g26600 85%
LOC_Os10g26633 35%
Group AT1G01090-TAIR-G
LOC_Os04g02900 74%
How can create the data structure that looks like this:
print Dumper \%big;
$VAR = { "Group AT1G01040-TAIR-G" => ['LOC_Os03g02970 69%'],
"Group AT1G01050-TAIR-G" => ['LOC_Os10g26600 85%','LOC_Os10g26633 35%'],
"Group AT1G01090-TAIR-G" => ['LOC_Os04g02900 74%']};
This is my attempt, but fail:
my %big;
while ( <> )开发者_如何学运维 {
chomp;
my $line = $_;
my $head = "";
my @temp;
if ( $line =~ /^Group/ ) {
$head = $line;
$head =~ s/[\r\s]+//g;
@temp = ();
}
elsif ($line =~ /^\t/){
my $cont = $line;
$cont =~ s/[\t\r]+//g;
push @temp, $cont;
push @{$big{$head}},@temp;
};
}
Here's how I'd do it:
my %big;
my $currentGroup;
while (my $line = <> ) {
chomp $line;
if ( $line =~ /^Group/ ) {
$big{$line} = $currentGroup = [];
}
elsif ($line =~ s/^\t+//) {
push @$currentGroup, $line;
}
}
You should probably add some additional error checking to this, e.g. an else
clause to warn about lines that don't match either regex. Also, check to see if $currentGroup
is undef
before pushing (in case the first line begins with a tab instead of "Group").
The biggest problem with your original code is that you're declaring and initializing $head
and @temp
inside the loop, which means they got reset on every line. Variables that need to persist across lines have to be declared outside the loop, as I've done with $currentGroup
.
I'm not quite sure what you're intending to accomplish with the s/[\r\s]+//g;
bit. \r
is included in \s
, so that means the same as s/\s+//g;
(which would strip all whitespace), but your desired result hash includes whitespace in your keys. If you want to strip trailing whitespace, you need to include an anchor: s/\s+\z//
.
Well, I don't want to give you an answer, so I'll just tell you to look at:
- perlref
- perlreftut
Well, there ya go :-).
Your pushing arrays to your hash item. You should just be pushing the values. (You don't need @temp
at all.)
push @{$big{$head}}, $cont;
Also $head
must be declared outside your loop, otherwise it looses its value after each iteration.
精彩评论