There are a number of things you need to correct aside from the hash related issues. First off, always use strictures (use strict; use warnings;). Use the three parameter version of open and lexical file handles (see the open in the sample code below). You don't need to initialise hashes and arrays. String interpolation is generally more readable than concatenated string fragments.
The following sample uses a "trick" that lets me use a string as an input file to save needing an external file. It's easier to see what's going on if you split to a variable list than to an array and much easier to validate the code. Your code is not consistent with your data so I've pretty much ignored you code and simply followed your "specification". Consider:
use strict;
use warnings;
my $str = <<STR;
AA SET1 0
AA SET2 1
AA SET3 0
BB SET1 0
BB SET3 0
CC SET1 2
CC SET2 3
STR
my %rows;
my %sets;
open my $fIn, '<', \$str or die "Can't open input file: $!\n";
while (defined (my $line = <$fIn>)) {
chomp $line;
my ($name, $set, $value) = split /\s+/, $line;
next if !defined $value;
$rows{$name}{$set} = $value;
++$sets{$set};
}
my @setNames = sort keys %sets;
print join ("\t", 'Name', @setNames), "\n";
for my $rowName (sort keys %rows) {
print join ("\t",
$rowName, map {defined $_ ? $_ : ''} @{$rows{$rowName}}{@setNa
+mes}),
"\n";
}
Prints:
Name SET1 SET2 SET3
AA 0 1 0
BB 0 0
CC 2 3
@{$rows{$rowName}}{@setNames} is a hash slice - it returns the list of values for the list if keys provided by @setNames. The map replaces undef values for missing entries with an empty string.
True laziness is hard work
|