Tek-Tips is the largest IT community on the Internet today!

Members share and learn making Tek-Tips Forums the best source of peer-reviewed technical information on the Internet!

  • Congratulations Rhinorhino on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

Making a Hash of it

Status
Not open for further replies.

Zdog

Technical User
Joined
Mar 6, 2003
Messages
4
Location
US
I'm trying to take an error file and summarize the results. Counting the number of errors per cell by error type.
Example input format:

SELECT Error1
COMMENT = "blah blah blah"} (4;76)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Structure ( lower left x, y ) ( upper right x, y )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cellx05 (0.98000, 1.08000) (0.98000, 1.18000)
cellx05 (1.12000, 1.08000) (1.12000, 1.18000)
cellx90 (2.32000, 1.39000) (2.40000, 1.39000)
cellx90 (2.32000, 1.53000) (2.40000, 1.53000)

SELECT Error2
COMMENT = "yada yada yada"} (4;76)

- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
Structure ( lower left x, y ) ( upper right x, y )
- - - - - - - - - - - - - - - - - - - - - - - - - - - - -
cellx05 (0.98000, 1.08000) (0.98000, 1.18000)
cellx90 (1.12000, 1.08000) (1.12000, 1.18000)
cellx90 (2.32000, 1.39000) (2.40000, 1.39000)
cellx90 (2.32000, 1.53000) (2.40000, 1.53000)


Each time a cell is listed equals one error.
I would like the output summarized as:

Cell Error1 Error2
cellx05 2 1
cellx90 2 3


I'm thinking that the way I'm going about this is all wrong, but as this is about my 5th attempt, I thought I would beg some help from the experts.
My code is as follows, I haven't even attempted to code the output portion:

$errorfile = "allcells.err";

open (IF, $errorfile) || die ("ERROR: Cannot open file: $!\n");
%Err1;
%Err2;
while (<IF>) {
if ($_ =~/SELECT\b (Error1|Error2)\b/){
my($errtype)=$1;
if ($_ =~ /(cell[\S]+)/ {
my($cell) = $1;
$Err1{$cell}++ if($errtype eq 'iError1');
$Err2{$cell}++ if($errtype eq 'Error2');
}
}
close <IF>;

}
 
What this suggests to me is a hash of hashes, with the cell names as keys in the &quot;outer&quot; hash and the error types as keys in the &quot;inner&quot; hash. Here's some code:
Code:
#!perl
use strict;

my %h;
my $errtype;

while (<DATA>)
{
    next unless /^(SELECT|cellx)/;
    chomp;
 
   if (/^SELECT\s+(Error\d+)/)
    {
        $errtype = $1;
        next;
    }
    if (/^(cellx\d+)/)
    {
        $h{$1}{$errtype}++;
    }
}

print &quot;Cell\tError1\tError2\n&quot;;
for my $k (sort keys %h)
{
    print &quot;$k\t&quot;;
    for my $j (sort keys %{$h{$k}})
    {
        print &quot;$h{$k}{$j}\t&quot;;
    }
    print &quot;\n&quot;;
}
Output with the data you posted:

Cell Error1 Error2
cellx05 2 1
cellx90 2 3

 
mikevh,

You're the best. Works like a champ. Don't suppose, purely for my edification, that you could explain the for loops that are printing the hash?


for my $k (sort keys %h)
{
print &quot;$k\t&quot;;
for my $j (sort keys %{$h{$k}})
{
print &quot;$h{$k}{$j}\t&quot;;
}

Thanks again!
 
for my $k (sort keys %h) #iterate over sorted &quot;outer&quot; hash keys
{
print &quot;$k\t&quot;; #print outer hash key followed by tab
for my $j (sort keys %{$h{$k}}) #iterate over sorted &quot;inner&quot; hash keys
{
print &quot;$h{$k}{$j}\t&quot;; #print the value pointed to by the combo of outer and inner key, followed by tab
}
print &quot;\n&quot;; #print newline at end of current &quot;row&quot;, before we go back to get next outer key
}

I don't mean to suggest that this is the only, or necessarily the best, way to do this.

For more on this, see the following Perl documentation:

perldsc
perlreftut
perlref
perllol
 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top