Andrej Kastrin wrote:
Dear Perl users,

below is three column, vertical bar separated file. First column refers to ID number, second designates name and the last one refers to corresponding value. There are 8 possible names: A, B, C, D, E, F, G and H (only first seven preset in my dataset)

1 | C | 0.404
1 | D | 0.824
1 | E | 1.761
1 | F | 0.148
1 | G | 1.860
2 | A | 1.420
2 | B | 0.571
2 | C | 0.467
2 | D | 1.824
3 | A | 0.191

Now I have to produce the following output.
1 | 0 | 0 | 0.404 | 0.824 | 1.761 | 0.148 | 1.860 ## 2 zeroes following ID number while there are no A and B names referring to ID 1 2 | 1.420 | 0.571 | 0.467 | 1.824 | 0 | 0 | 0 | 0 | 0 ## 4 zeroes at the end while the are no E, F, G, H names referring to ID 2
3 | 0.191 | 0 | 0 | 0 | 0 | 0 | 0 | 0
My code:

####################################
#!/usr/bin/perl

use strict;
use warnings;

my %hash = ();

while (<>) {
my ($id, $name, $value) = split;
push( @{$hash{$id}}, $value);
}

foreach my $id (sort keys %hash) {
print "$id @{$hash{$id}}\n";
}
####################################

which produce the output below. I have no idea how to place zeroes, where there are no entry for particular name.

1 0.404 0.824 1.761 0.148 1.860
2 1.420 0.571 0.467 1.824
3 0.191


Thanks in advance for any suggestion,

Andrej


Let autovivication do the work for you. If you assign to an array element that doesn't exist, it does:

use strict;
use warnings;
use Data::Dumper;

local $_ = q{
1 | C | 0.404
1 | D | 0.824
1 | E | 1.761
1 | F | 0.148
1 | G | 1.860
2 | A | 1.420
2 | B | 0.571
2 | C | 0.467
2 | D | 1.824
3 | A | 0.191
};

my %ids;
my %code;
@code{('A'..'G')} = (0..6);

while (m/^\s*(.*?)\s*$/mg) {
    my ($id, $name, $value) = split /\s*\|\s*/, $1;
    $ids{$id}->[$code{$name}] += $value;
}

print Dumper(\%ids), "\n";

__END__

The %ids hash contains the data, and the %code hash associates names with array positions, so $code{$name} is a position in an array.

Each $ids{$id} item is autovivified by "+= $value," and each anonymous array in %ids is autovivified by "->[$code{$name}]."

Without autovivication, this would have been a larger program, but why do that?

:)

PS.
You can probably figure out how to format the data for output.


--
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]
<http://learn.perl.org/> <http://learn.perl.org/first-response>


Reply via email to