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 bkrike on being selected by the Tek-Tips community for having the most helpful posts in the forums last week. Way to Go!

increment totals across multiple input lines 1

Status
Not open for further replies.

MakAtak

Technical User
Nov 4, 2005
5
GB
Hi,

I'm struggling with a perl script that increments totals and outputs values when a new ref number is encountered.

my input looks something like:

REC>0002>000046>18000 >TSOP>M>18000 000046>D0
REC>0006>000077>18000 >TSOP>M>18000 000046>D0
REC>0006>000077>18000 >TSOP>C>18000 000046>D0
REC>0006>000077>18000 >TSOP>C>18000 000046>D0
REC>0005>000249>18000 >TSOP>M>18000 000046>D0
REC>0001>100041>18000 >TSOP>M>18000 000046>D0
REC>0001>100041>18000 >TSOP>C>18000 000046>D0
REC>0001>100041>18000 >TSOP>C>18000 000046>D0
REC>0001>100041>18000 >TSOP>C>18000 000046>D0
REC>0002>000146>18000 >TSOP>M>18000 000046>D0
REC>0001>000243>18000 >TSOP>M>18000 000046>D0
REC>0001>000243>18000 >TSOP>C>18000 000046>D0
REC>0001>000243>18000 >TSOP>C>18000 000046>D0
REC>0001>000243>18000 >TSOP>C>18000 000046>D0
REC>0001>000243>18000 >TSOP>C>18000 000046>D0
REC>0003>100045>18000 >TSOP>M>18000 000046>D0

The second field is the number of pages, and the third field is the ref number. field six is the duplicate flag,
"M" = master, "C" = copy.
I have to output this data as follows:

Ref: 000046 totalOrig: 2 totalDups: 0 totalPrinted: 2
Ref: 000077 totalOrig: 6 totalDups: 12 totalPrinted: 18
Ref: 000249 totalOrig: 5 totalDups: 0 totalPrinted: 5
Ref: 100041 totalOrig: 1 totalDups: 3 totalPrinted: 4
Ref: 000146 totalOrig: 2 totalDups: 0 totalPrinted: 2
Ref: 000243 totalOrig: 1 totalDups: 4 totalPrinted: 5
Ref: 100045 totalOrig: 3 totalDups: 0 totalPrinted: 3

If the current ref num is the same as the previous, then add the number of pages to the number of duplicates if dup flag equals "C", and increment total pages by page count.

My script seems to be using the previous value of totalDups, and I'm not sure where I'm going wrong. My ouptput is as follows:

Ref: 000046 totalOrig: 2 totalDups: 0 totalPrinted: 2
Ref: 000077 totalOrig: 6 totalDups: 0 totalPrinted: 6
Ref: 000249 totalOrig: 5 totalDups: 12 totalPrinted: 17
Ref: 100041 totalOrig: 1 totalDups: 0 totalPrinted: 1
Ref: 000146 totalOrig: 2 totalDups: 3 totalPrinted: 5
Ref: 000243 totalOrig: 1 totalDups: 0 totalPrinted: 1
Ref: 100045 totalOrig: 3 totalDups: 4 totalPrinted: 7

This has had me and a colleague stumped for two days now. Although we are both quite new to perl. The code is below.
Thanks in advance for any tips/pointers as to where I am going wrong.

@ARGV == 1 or die "Usage: $0 inputFile \n";

$prevRef = "XXX";
$totalOrig = 0;
$totalDups = 0;
$totalPrinted = 0;

open INPUTFILE, "$ARGV[0]" or die "error: $ARGV[0] - $!";

while (<INPUTFILE>) {

@recordArray = split (/>/, $_);

$numPages = $recordArray[1];
$refNum = $recordArray[2];
$dupInd = $recordArray[5];

if ($prevRef eq $refNum){
&incrementTots;
next;
}
else{
&incrementTots;
&printDetail;
}

$prevRef = $refNum;

}

#
# subroutine to increment totals
#
sub incrementTots{
if ($dupInd eq "M"){
$totalOrig += $numPages;
}
else{
$totalDups += $numPages;
}
$totalPrinted += $numPages;
}

#
# print a detail line
#

sub printDetail{
print "Ref: $refNum totalOrig: $totalOrig totalDups: $totalDups totalPrinted: $totalPrinted\n";
$totalOrig = 0;
$totalDups = 0;
$totalPrinted = 0;
}
 
Don't you want to flip
else{
&incrementTots;
&printDetail;
}

to
else{
&printDetail;
&incrementTots;
}
 
There's all sorts of logical gotchas laying in wait for you when trying to do it in the method you're trying:

Alternative: Use a hash data structure, keyed off your refnum (actually a hash of hashes).


Code:
[url=http://perldoc.perl.org/functions/my.html][black][b]my[/b][/black][/url] [blue]%myHash[/blue]=[red]([/red][red])[/red][red];[/red]
[black][b]my[/b][/black] [blue]@recordArray[/blue]=[red]([/red][red])[/red][red];[/red]
[black][b]my[/b][/black] [blue]$numPages[/blue][red];[/red]
[black][b]my[/b][/black] [blue]$refNum[/blue][red];[/red]
[black][b]my[/b][/black] [blue]$dupInd[/blue][red];[/red]

[olive][b]while[/b][/olive] [red]([/red]<DATA>[red])[/red] [red]{[/red]
  [blue]@recordArray[/blue] = [url=http://perldoc.perl.org/functions/split.html][black][b]split[/b][/black][/url] [red]/[/red][purple]>[/purple][red]/[/red][red];[/red]
  [blue]$numPages[/blue] = [blue]$recordArray[/blue][red][[/red][fuchsia]1[/fuchsia][red]][/red][red];[/red]
  [blue]$refNum[/blue]   = [blue]$recordArray[/blue][red][[/red][fuchsia]2[/fuchsia][red]][/red][red];[/red]
  [blue]$dupInd[/blue]   = [blue]$recordArray[/blue][red][[/red][fuchsia]5[/fuchsia][red]][/red] eq [red]"[/red][purple]C[/purple][red]"[/red][red];[/red]
  [blue]$myHash[/blue][red]{[/red][blue]$refNum[/blue][red]}[/red][red]{[/red]Total[red]}[/red] += [blue]$numPages[/blue][red];[/red]
  [blue]$myHash[/blue][red]{[/red][blue]$refNum[/blue][red]}[/red][red]{[/red][blue]$dupInd[/blue]?[red]"[/red][purple]Dupes[/purple][red]"[/red]:[red]"[/red][purple]Originals[/purple][red]"[/red][red]}[/red] += [blue]$numPages[/blue][red];[/red]
[red]}[/red]
[olive][b]foreach[/b][/olive] [red]([/red] [url=http://perldoc.perl.org/functions/sort.html][black][b]sort[/b][/black][/url] [url=http://perldoc.perl.org/functions/keys.html][black][b]keys[/b][/black][/url] [blue]%myHash[/blue] [red])[/red] [red]{[/red]
  [url=http://perldoc.perl.org/functions/printf.html][black][b]printf[/b][/black][/url] [red]"[/red][purple]Ref: %s  totalOrig: %d totalDupes: %d totalPrinted: %d[purple][b]\n[/b][/purple][/purple][red]"[/red],[blue]$_[/blue],[blue]$myHash[/blue][red]{[/red][blue]$_[/blue][red]}[/red][red]{[/red]Originals[red]}[/red], [blue]$myHash[/blue][red]{[/red][blue]$_[/blue][red]}[/red][red]{[/red]Dupes[red]}[/red],[blue]$myHash[/blue][red]{[/red][blue]$_[/blue][red]}[/red][red]{[/red]Total[red]}[/red][red];[/red]
[red]}[/red]


[teal]__DATA__[/teal]
[teal]REC>0002>000046>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0006>000077>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0006>000077>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0006>000077>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0005>000249>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0001>100041>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0001>100041>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0001>100041>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0001>100041>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0002>000146>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0001>000243>18000  >TSOP>M>18000  000046>D0[/teal]
[teal]REC>0001>000243>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0001>000243>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0001>000243>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0001>000243>18000  >TSOP>C>18000  000046>D0[/teal]
[teal]REC>0003>100045>18000  >TSOP>M>18000  000046>D0[/teal]
 
Thanks for that.

could you explain what's being done on this line please?

$myHash{$refNum}{$dupInd?"Dupes":"Originals"} += $numPages;
 
Well to explain that, you'll first need to note:
Code:
$dupInd   = $recordArray[5] eq "C";

This sets $dupInd to be true if this is a copy ("C"), and false if it is an "M".

Code:
$myHash{$refNum}{$dupInd?"Dupes":"Originals"} += $numPages;

In this case, we're using the ternary (some call it trinary) operator. In it's simplest form:

Code:
a = b ? c : d;

is equivalent to :
Code:
if (b) {
  a = c;
} else {
  a = d;
}

In my code, it adds $numPages to $myHash{$refNum}{Dupes} if $dupInd is nonzero (true) or $myHash{$refNum}{Originals} of $dupInd is zero (false).

 
Status
Not open for further replies.

Part and Inventory Search

Sponsor

Back
Top