For some reason I must have thought that \& was the correct way to return a reference...anyway it worked out neatly:
#!/usr/bin/perl -w
use strict;
my %all;
open(INPUT,"<coconet.dat") || die "Can't open coconet.dat";
while (<INPUT>) {
if ($_ =~ /^#/) { next }
my ($src, $dest, $bytes) = split;
# hash of hashes holds the from->to transmission TOTALS; we do not
+ keep all the data
$all{$src}{$dest}+=$bytes;
}
close(INPUT);
# simple use of map to create array of references to hashes: my @refli
+st = map { \%{$all{$_}} } keys %all;
# so...create an array of references to arrays (from map callback) of
+scalars and REFS TO existing hashes and new anonymous arrays!
my @reflist = sort { $$b[2] <=> $$a[2] } map buildlist($_), keys %all;
+
# sort by the total of TOTALS
foreach my $ref (@reflist) {
print "$$ref[0] $$ref[2]\n";
# the next two are the same:
foreach my $line (@{$ref->[3]}) { print "\t$line ${$ref->[1]}{$li
+ne}\n" }
# foreach my $line (@{$$ref[3]}) { print "\t$line ${$$ref[1]}{$lin
+e}\n" }
}
sub buildlist {
my $site = $_;
my @tmp;
$tmp[0]=$site;
$tmp[1]=\%{$all{$site}};
foreach (keys %{$tmp[1]}) { $tmp[2]+=${$tmp[1]}{$_} }
# make element 3 a reference to an anonymous array of scalars (the
+ dest site names, ranked)
@{$tmp[3]} = sort { ${$tmp[1]}{$b} <=> ${$tmp[1]}{$a} } keys %{$tm
+p[1]};
return \@tmp; # 0=site name, 1=hash ref, 2=total bytes for all t
+ransmissions from site, 3=ranked dest names ref
}
__DATA__
2000 lines, eg:
gilligan.crew.hut lovey.howell.hut 4721
thurston.howell.hut lovey.howell.hut 4046
professor.hut ginger.girl.hut 5768
gilligan.crew.hut laser3.copyroom.hut 9352
gilligan.crew.hut maryann.girl.hut 1180
fileserver.copyroom.hut thurston.howell.hut 2548
skipper.crew.hut gilligan.crew.hut 1259
This is more complex, but no longer than the solution in the book -- but the solution in the book does not create a permanent data structure either (goal was to just print ranked totals).
|