Re: Perl Hash
by NetWallah (Canon) on Apr 17, 2013 at 04:31 UTC
|
Here is one way to do it:
use strict;
use warnings;
my %h;
while (<DATA>){
chomp;
next if length($_) < 30;
my ($k1, $k2,$k3, $val) = unpack("A8 x1 A15 x1 A33 x1 A5", $_);
$h{$k1}{$k2}{$k3} += $val;
}
for my $k1 (sort keys %h){
print "$k1\n";
for my $k2 ( sort keys %{ $h{$k1} } ) {
print "\t$k2\n";
for my $k3 ( sort keys %{ $h{$k1}{$k2} } ) {
print "\t\t$k3 $h{$k1}{$k2}{$k3}\n";
}
}
}
__DATA__
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 20.32
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 24.00
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 24.00
prints:
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 1 44.32
Summary1
Detial_Summary1
EMC CHECK1 abcdefghi AZ_checker 1 44.59
"I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
-- Dr. Cox, Scrubs
| [reply] [d/l] [select] |
|
|
Hi,
Thanks a lot for the inputs.
how can i ge this ouput for the same code.
<DATA>
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 1 44.32
EMC CHECK Grand_Total 1 44.32
Summary1
Detial_Summary1
EMC CHECK1 abcdefghi AZ_checker 1 44.59
EMC CHECK1 Grand_Total 1 44.59
</DATA>
| [reply] |
|
|
$h{$k1}{$k2}{+substr($k3,0,10) . " Grand Total"} += $val;
This is a kludgy way to do it, but, given your sparse data definition, it does put out a grand total.
A more robust implementation would require one more level of hashing - I leave that as an exercise for you to implement.
"I'm fairly sure if they took porn off the Internet, there'd only be one website left, and it'd be called 'Bring Back the Porn!'"
-- Dr. Cox, Scrubs
| [reply] [d/l] |
Re: Perl Hash
by CountOrlok (Friar) on Apr 17, 2013 at 04:25 UTC
|
Where to begin...
First, it would make it easier to figure out what is going on if you could reformat the input/output (put them in code tags).
I got several issues with this code but I think the main issue you is that you have a variable named $Summry and one called $Summary which is undefined. Then you have $Detial_Summary which is also undefined
BTW, the first if-else clause is unnecessary because of auto-vivification.
I would rather combine (i.e. join) the fields on an uncommon character like '^' or '|' instead of spaces. It later makes it easier to split the fields back rather than using substr. | [reply] |
|
|
$fulllookupKey = Summary."\t".Detial_Summary."\t".Name."\t".Location."
+\t".Sub_Location."\t".
<code>
if (exists($output{$fulllookupKey})){
$output{$fulllookupKey}->[0] += $Count;
$output{$fulllookupKey}->[1] += $Amount;
}
else
{
$output{$fulllookupKey}->[0] = $Count;
$output{$fulllookupKey}->[1] = $Amount;
}
for my $key (sort keys %output){
my $Summary = substr($key,0,7);
my $Detial_Summary = substr($key,8,7);
my $Source = substr($key,16,100);
print Out $Summary;." \t" . " \t" . " \t". "\t" ."\t" ."\t" ."\n";
print Out " \t" . $Detial_Summary." \t" . " \t" . " \t". "\t" ."\t" ."
+\t" . "\t" ."\n";
print Out " \t" . " \t" . $Source."\t".sprintf("%.2f", $output{$key}->
+[0])."\t".sprintf("%.2f", $output{$key}->[1])."\n";
}
<INPUT>
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 20.32
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 24.32
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 24.00
<INPUT>
<OUTPUT>: (what i got)
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 1 20.32
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 1 24.32
Summary1
Detial_Summary1
EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1
Detial_Summary1
EMC CHECK1 abcdefghi AZ_checker 1 24.00
</OUTPUT>
Expected Output:
<OUTPUT>
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 1 44.32
Summary1
Detial_Summary1
EMC CHECK1 abcdefghi AZ_checker 1 24.59
</OUTPUT>
| [reply] [d/l] |
|
|
| [reply] |
|
|
Hashes of Hash in perl
by Rajsai2825 (Novice) on Apr 17, 2013 at 09:39 UTC
|
Hi,
could you please help on this?
MY Code:
$fulllookupKey = $field[1]."\t". $field[2]."\t". $field[3]."\
+t".$field[4]."\t".$field[5];
$RescatKey = $field[1];
$RessubcatKey = $field[2];
$MasterSrkey = $field[3];
$field[4] =~ s/^\s+//;
$field[21] =~ s/^\s+//;
$Count = $field[6];
$Amount = $field[7];
if (exists($output{$RescatKey}{$RessubcatKey}{$fulllookupKey}))
+
{
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[0] += $fie
+ld[6];
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[1] += $fie
+ld[7];
}
else
{
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[0] = $fiel
+d[6];
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[1] = $fiel
+d[7];
}
}
for my $k1 (sort keys %output){
print "$k1\n";
for my $k2 ( sort keys %{ $output{$k1} } ) {
print "\t$k2\n";
for my $k3 ( sort keys %{ $output{$k1}{$k2} } ) {
my $Source = substr($k3,16,100);
my $Source1 = substr($k3,16,07);
print "\t\t$Source $output{$k1}{$k2}{$k3}->[0]\t$output{$k1}{$
+k2}{$k3}->[1]\n";
print "\t\t$Source1\t TOTAL \t$output{$k1}{$k2}{$k3}->[1]\t$outpu
+t{$k1}{$k2}{$k3}->[0]\n";
}
}
}
INPUT is:
<code>
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 20.32
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 24.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 10.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 14.00
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 24.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 10.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 14.00
</code>
OUTPUT expected is:
Summary
Detial_Summary
EMC CHECK abcdefghi AZ_checker 2 44.32
EMC CHECK KBCDEFGHI AZ_checker 2 24.00
EMC CHECK TOTAL 4 64.32
EMC CHECK1 abcdefghi AZ_checker 2 44.59
EMC CHECK1 HGIJHKKIF AZ_checker 2 24.00
EMC CHECK1 TOTAL 4 68.59
Detial_Summary TOTAL 8 132.91
Summary TOTAL 8 132.91
| [reply] [d/l] [select] |
|
|
How about this? Still lots of open questions...
I have ignored the first 3 columns as they do not seem to make any difference (even though they have different entries, these differences are ignored in your desired output). In order to check whether columns line up properly, open in Excel with TAB delimited.
use strict;
use warnings;
my %output;
my %total;
while (my $line = <DATA>){
chomp $line;
my @field = split /\s+/, $line;
# fields 0, 1, 2 do seem to be required
$output{$field[3]}{$field[4]}{$field[5]}{COUNT} += $field[6];
$output{$field[3]}{$field[4]}{$field[5]}{VALUE} += $field[7];
$total{$field[3]}{COUNT} += $field[6];
$total{$field[3]}{VALUE} += $field[7];
$total{TOTAL}{COUNT} += $field[6];
$total{TOTAL}{VALUE} += $field[7];
}
print "Summary\n";
print "\tDetailed Summary\n";
for my $k1 (sort keys %output){
for my $k2 ( sort keys %{ $output{$k1} } ) {
for my $k3 ( sort keys %{ $output{$k1}{$k2} } ) {
print "\t\tEMC\t$k1\t$k2\t$k3\t$output{$k1}{$k
+2}{$k3}{COUNT}\t$output{$k1}{$k2}{$k3}{VALUE}\n";
}
}
print "\t\tEMC\t$k1\tTOTAL\t\t$total{$k1}{COUNT}\t$total{$k1}{
+VALUE}\n";
}
print "\tDetailed Summary\tTOTAL\t\t$total{TOTAL}{COUNT}\t$total{TOTAL
+}{VALUE}\n";
print "Summary\n";
__DATA__
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 20.32
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 24.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 10.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 14.00
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 24.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 10.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 14.00
| [reply] [d/l] |
|
|
| [reply] |
|
|
| [reply] |
|
|
|
|
|
|
|
Just one friendly piece of advice: Please stick to one convention when using variable names. You have some variables with like $Summary (a convention no one uses), some like $fulllookupKey (which should really have been $fullLookupKey) and I also saw something like $load_data in one of your post.
Sticking to one convention helps you more than anyone else. You don't need to keep going back to check how you spelled that variable.
| [reply] |
|
|
Hi Rajsai2825,
I know you have been given a workable script, but I just want to point out that you can do all your "stuff" using just a hash and function unpack. As shown below. (ofcourse, I wouldn't drop all the "jar of honey" on your laps!:))
use warnings;
use strict;
my %input;
my $total;
my $grand_total;
while (<DATA>) {
chomp;
next if /^$/;
my ( $k1, $k2, $k3, $k4, $k5 ) = unpack("x25 A10 A10 x1 A10 x1 A1
+x1 A5");
$total += $k4;
$grand_total += $k5;
push @{ $input{'summary'}{'Detial_Summary'}{$k1}{$k2}{$k3}{ ++$k4
+} }, $k5;
}
push @{ $input{'summary'}{'TOTAL'}{$total} }, $grand_total;
use Data::Dump;
dd \%input;
__DATA__
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 20.32
Summary Detial_Summary EMC CHECK abcdefghi AZ_checker 1 24.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 10.00
Summary Detial_Summary EMC CHECK KBCDEFGHI AZ_checker 1 14.00
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 20.59
Summary1 Detial_Summary1 EMC CHECK1 abcdefghi AZ_checker 1 24.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 10.00
Summary1 Detial_Summary1 EMC CHECK1 HGIJHKKIF AZ_checker 1 14.00
OUTPUT
{
summary => {
Detial_Summary => {
"EMC CHECK" => {
" abcdefghi" => { AZ_checker => { 2 => [20.32,
+ "24.00"] } },
" KBCDEFGHI" => { AZ_checker => { 2 => ["10.00
+", "14.00"] } },
},
"EMC CHECK1" => {
" abcdefghi" => { AZ_checker => { 2 => [20.59,
+ "24.00"] } },
" HGIJHKKIF" => { AZ_checker => { 2 => ["10.00
+", "14.00"] } },
},
},
TOTAL => { 8 => [136.91] },
},
}
If you tell me, I'll forget.
If you show me, I'll remember.
if you involve me, I'll understand.
--- Author unknown to me
| [reply] [d/l] [select] |
|
|
Your code is incomplete, it doesn't read input
| [reply] |
|
|
Please find the subroutine:
while (chomp(@field = split (/\t/, <FILE>)))
{
next unless ($field[0] =~ /^$USG_REC_IND/);
foreach my $key ( keys %load_data ) {
{
if (length($key) == 0)
{
next;
}
}
}
$fulllookupKey = $field[1]."\t". $field[2]."\t". $field[3]."\t".$
+field[4]."\t".$field[5];
$RescatKey = $field[1];
$RessubcatKey = $field[2];
$MasterSrkey = $field[3];
$field[4] =~ s/^\s+//;
$field[21] =~ s/^\s+//;
$Count = $field[6];
$Amount = $field[7];
if (exists($output{$RescatKey}{$RessubcatKey}{$fulllookupKey}))
{
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[0] += $fie
+ld[6];
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[1] += $fie
+ld[7];
}
else
{
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[0] = $fiel
+d[6];
$output{$RescatKey}{$RessubcatKey}{$fulllookupKey}->[1] = $fiel
+d[7];
}
}
for my $k1 (sort keys %output){
print "$k1\n";
for my $k2 ( sort keys %{ $output{$k1} } ) {
print "\t$k2\n";
for my $k3 ( sort keys %{ $output{$k1}{$k2} } ) {
my $Source = substr($k3,16,100);
print "\t\t$Source $output{$k1}{$k2}{$k3}->[0]\t$output{$k1}{$k2}
+{$k3}->[1]\n";
print "\t\t$Source1\t TOTAL \t$output{$k1}{$k2}{$k3}->[1]\t$outpu
+t{$k1}{$k2}{$k3}->[0]\n";
}
}
}
close (OUT);
}
| [reply] [d/l] |