How do I get to anonymous arrays?

The following code generates a list of the average number of clients connected to the subnet. Currently I have to run it through sort | uniq | grep -v HASH.

Trying to keep it all in perl, this doesn't work:

foreach $subnet (keys %{keys %{keys %days}}) {
    print "$subnet\n";
}

      

A source:

foreach $file (@ARGV) {
        open(FH, $file) or warn("Can't open file $file\n");
        if ($file =~ /(2009\d{4})/) {
            $dt = $+;
        }
        %hash = {};
        while(<FH>) {
            @fields = split(/~/);
            $subnet = $fields[0];
            $client = $fields[2];
            $hash{$subnet}{$client}++;
        }
        close(FH);
        $file = "$dt.csv";
        open(FH, ">$file") or die("Can't open $file for output");
        foreach $subnet (sort keys %hash) {
                $tot = keys(%{$hash{$subnet}});
                $days{$dt}{$subnet} = $tot;
                print FH "$subnet,$tot\n";
                push @{$subnet}, $tot;
        }
        close(FH);
    }

    foreach $day (sort keys %days) {
        foreach $subnet (sort keys %{$days{$day}}) {
            $tot = $i = 0 ;
            foreach $amt (@{$subnet}) {
                $i++;
                $tot += $amt;
            }
            print "$subnet," . int($tot/$i) . "\n";
        }
    }

      

How can I eliminate the need for sorting | uniq process outside of perl? The last foreach gets me subnet ids, which are "anonymous" names for arrays. It generates these multiple times (one for each day the subnet was used).

+1


a source to share


2 answers


but it turned out to be easier than concatenating the table in excel.

In fact, modules like Spreadsheet :: ParseExcel do this very easily, in most cases. You still have to deal with the strings as if they were from a CSV or "A1" destination, but you don't need to take the export step. And then you can output with Spreadsheet :: WriteExcel !

I used these modules to read a table of several hundred checks, sort, order, and pass the content and write to a new one for delivery to the accountant.


In this part:



foreach $subnet (sort keys %hash) {
        $tot = keys(%{$hash{$subnet}});
        $days{$dt}{$subnet} = $tot;
        print FH "$subnet,$tot\n";
        push @{$subnet}, $tot;
}

      

$ subnet is a string, but you are using it in the last statement as an array reference. Since you don't have strictures , it treats it as a soft reference to a variable with a name similar to the $ subnet content, which is fine if you really want to, but it's confusing. As for clarifying the last part ...

Update. I guess this is what you are looking for, where the subnet value is only saved if it hasn't appeared before, even from another day (?):

use List::Util qw(sum); # List::Util was first released with perl 5.007003 (5.7.3, I think)
my %buckets;
foreach my $day (sort keys %days) {
    foreach my $subnet (sort keys %{$days{$day}}) {
        next if exists $buckets{$subnet}; # only gives you this value once, regardless of what day it came in
        my $total = sum @{$subnet}; # no need to reuse a variable
        $buckets{$subnet} = int($total/@{$subnet}; # array in scalar context is number of elements
    }
}

use Data::Dumper qw(Dumper);
print Dumper \%buckets;

      

+2


a source


Building on @ Anonymous suggestions, I built a hash of subnet names to access arrays:

..



            push @{$subnet}, $tot;
            $subnets{$subnet}++;
    }
    close(FH);
}

use List::Util qw(sum); # List::Util was first released with perl 5.007003

foreach my $subnet (sort keys %subnets) {
    my $total = sum @{$subnet}; # no need to reuse a variable
    print "$subnet," . int($total/@{$subnet}) . "\n"; # array in scalar context is number of elements
}

      

Not sure if this is the best solution, but I have no more duplicates.

0


a source







All Articles