R
removeps groups
My perl script reads lines of a file, or rows of a database. The first column is the key (the id, an integer), and for each distinct key an entry should be added into the hashmap. The second column is a string (the name). The third and fourth columns will go into the first and second array of thekey-value, respectively. So if the file is (the 4 columns are tab-separated):
1 First Id 2 3
1 First Id 2 4
2 Second Id 3 4
the hash will contain two items. The first item has key 1. The value has one string with value "First Id", two arrays, and the first array is (2,2) and the second is (3,4). The second item has key 2. The value has one string with value "Second Id", two arrays, (3) and (4). In Java the structurewould be Map<Integer, Triplet<String, List<Integer>, List<Integer>>>.
To model this data structure in perl I had to do stuff like the following, which works on Strawberry Perl and Linux Perl:
my %data; # map of id to [ Name, ArrayOfInt, ArrayOfInt ]
my $value = $data{$id};
my @tmpvalue = ($name, [], []);
$value = \@tmpvalue;
$data{$id} = $value;
push(@{$$value[1]}, $firstInt);
I don't know why the particular combination of $ @ {} \ works, but it does.Questions are:
(1) Is this the most efficient way?
(2) Why does it work?
The full script is below
#!/usr/bin/perl
use strict;
use warnings;
my %data; # map of id to [ Name, ArrayOfInt, ArrayOfInt ]
open sqlData, "hash-rows.txt" || die $!;
while (<sqlData>)
{
chomp $_;
my @row = split '\t', $_;
my $id = $row[0];
my $name = $row[1];
my $firstInt = $row[2];
my $secondInt = $row[3];
my $value = $data{$id};
if (not defined $value)
{
my @tmpvalue = ($name, [], []);
$value = \@tmpvalue;
$data{$id} = $value;
}
push(@{$$value[1]}, $firstInt);
push(@{$$value[2]}, $secondInt);
}
foreach my $id (keys %data)
{
my $value = $data{$id};
my $name = $$value[0];
my @firstInts = @{$$value[1]};
my @secondInts = @{$$value[2]};
print "ENTRY\n id=$id\n name=$name\n firstInts=(@firstInts)\n secondInts=(@secondInts)\n";
}
ENTRY
id=1
name=First
firstInts=(Id Id)
secondInts=(2 2)
ENTRY
id=2
name=Second
firstInts=(Id)
secondInts=(3)
1 First Id 2 3
1 First Id 2 4
2 Second Id 3 4
the hash will contain two items. The first item has key 1. The value has one string with value "First Id", two arrays, and the first array is (2,2) and the second is (3,4). The second item has key 2. The value has one string with value "Second Id", two arrays, (3) and (4). In Java the structurewould be Map<Integer, Triplet<String, List<Integer>, List<Integer>>>.
To model this data structure in perl I had to do stuff like the following, which works on Strawberry Perl and Linux Perl:
my %data; # map of id to [ Name, ArrayOfInt, ArrayOfInt ]
my $value = $data{$id};
my @tmpvalue = ($name, [], []);
$value = \@tmpvalue;
$data{$id} = $value;
push(@{$$value[1]}, $firstInt);
I don't know why the particular combination of $ @ {} \ works, but it does.Questions are:
(1) Is this the most efficient way?
(2) Why does it work?
The full script is below
#!/usr/bin/perl
use strict;
use warnings;
my %data; # map of id to [ Name, ArrayOfInt, ArrayOfInt ]
open sqlData, "hash-rows.txt" || die $!;
while (<sqlData>)
{
chomp $_;
my @row = split '\t', $_;
my $id = $row[0];
my $name = $row[1];
my $firstInt = $row[2];
my $secondInt = $row[3];
my $value = $data{$id};
if (not defined $value)
{
my @tmpvalue = ($name, [], []);
$value = \@tmpvalue;
$data{$id} = $value;
}
push(@{$$value[1]}, $firstInt);
push(@{$$value[2]}, $secondInt);
}
foreach my $id (keys %data)
{
my $value = $data{$id};
my $name = $$value[0];
my @firstInts = @{$$value[1]};
my @secondInts = @{$$value[2]};
print "ENTRY\n id=$id\n name=$name\n firstInts=(@firstInts)\n secondInts=(@secondInts)\n";
}
ENTRY
id=1
name=First
firstInts=(Id Id)
secondInts=(2 2)
ENTRY
id=2
name=Second
firstInts=(Id)
secondInts=(3)