Prince99 has asked for the wisdom of the Perl Monks concerning the following question:

Please help me oh wise monks. My boss(not a professor) needs this code to work for a client, but I can't seem to accomplish his goals the way he wants to. I will post my code and try to explain as best I can. Any help would be appreciated.
$DAT = "/where/my/file/is"; Main: { &Open_File; &Read_File; &Close_File; &Sort_File(@Claim_Number); } sub Sort_File { @T = sort { $a <=> $b || $a cmp $b } @_; foreach $T(@T){ } for ($x = 0; $x < $sz; $x++){ print "$Claim_Number[$T[$x]]\n";#this is the format + of the cod +e statement that my boss wants in the program. He + wants to be able +to replace $Claim_Number with another field. } } sub Read_File { $sz = 0; while(<CLAIMS>) { $x = $_; while(length($x gt 0)) { $_ = substr($x, 0, 434); $x = substr($x, 434); $_ = " ".$_; $Claim_Batch_Number[$sz] = substr($_,1,8); $Claim_Number[$sz] = substr($_,9,6); $Claim_Type[$sz] = substr($_,15,2); $Payment_Direct[$sz] = substr($_,17,2); $Pharmacy_Number[$sz] = substr($_,19,6); $Chain_Number[$sz] = substr($_,25,4); $Pharmacy_Name[$sz] = substr($_,29,30); $Reject_Code_1[$sz] = substr($_,59,4); $Reject_Code_2[$sz] = substr($_,63,4); $RX_Number[$sz] = substr($_,67,8); $RX_Date[$sz] = substr($_,75,8); $Drug_Type_Code[$sz] = substr($_,83,2); $National_Drug_Code[$sz] = substr($_,85,11); $Product_Name[$sz] = substr($_,96,25); $NewRefill_Indicator[$sz] = substr($_,121,1); $Metric_Quantity[$sz] = substr($_,122,8); $Days_Supply[$sz] = substr($_,130,3); $Ingredient_Cost_Billed[$sz] = substr($_,133,8); $Ingredient_Cost_Paid[$sz] = substr($_,141,8); $Dispensing_Fee[$sz] = substr($_,149,8); $Copay[$sz] = substr($_,157,8); $Tax[$sz] = substr($_,165,6); $Total_Amount_Paid[$sz] = substr($_,171,8); $UCR_Amount[$sz] = substr($_,179,8); $Member_Birthdate[$sz] = substr($_,187,8); $Member_Sex[$sz] = substr($_,195,1); $Cardholder_Number[$sz] = substr($_,196,10); $Member_Number[$sz] = substr($_,206,2); $Alternater_Card_Number[$sz]= substr($_,208,20); $Patient_Relationship[$sz] = substr($_,228,2); $Physician_Number[$sz] = substr($_,230,14); $Diagnosis_Code[$sz] = substr($_,244,6); $PDM_System_Number[$sz] = substr($_,250,4); $PDM_Sponsor_Number[$sz] = substr($_,254,8); $PDM_Group_Number[$sz] = substr($_,262,16); $Group_Number[$sz] = substr($_,278,20); $Generic_Code[$sz] = substr($_,298,1); $Mac_Number[$sz] = substr($_,299,2); $Daw_Indicator[$sz] = substr($_,301,1); $Therapeutic_Class_Code[$sz] = substr($_,302,6); $RX_OTC_Code[$sz] = substr($_,308,1); $GPI[$sz] = substr($_,309,14); $Exception_Code[$sz] = substr($_,323,2); $Override_Code[$sz] = substr($_,325,2); $Period_Ending[$sz] = substr($_,327,8); $Paid_Date[$sz] = substr($_,335,8); $Compound_Code[$sz] = substr($_,343,2); $Batch_Date[$sz] = substr($_,345,8); $Claim_Counter[$sz] = substr($_,353,2); $Mail_Order[$sz] = substr($_,355,1); $Benefit_Code[$sz] = substr($_,356,16); $AWP[$sz] = substr($_,372,8); $Claim_Indicator[$sz] = substr($_,380,1); $Drug_Preference_Indicator[$sz] = substr($_,381,1); $Pricing_Indicator[$sz] = substr($_,382,1); $Drug_Manufacturer[$sz] = substr($_,383,10); $Controlled_Substance[$sz] = substr($_,393,5); $Patient_Last_Name[$sz] = substr($_,398,20); $Patient_First_Name[$sz] = substr($_,418,15); $Patient_Middle_Initial[$sz] = substr($_,433,1); $Third_Party_Code[$sz] = substr($_,434,1); $sz++; } }#End While } sub Open_File { open(CLAIMS, $DAT) || die "CANNOT OPEN FILE"; } sub Close_File { close(CLAIMS); } The output comes out as such: 002224 002224 002225 002250 002252 000340 003072 003074 003075 002419 002420 000760 000762 001537 001538 001539 001540 001541 000845 002982 000339 000340 000569 000584 002965 000099 003516 003519 003526 001371 001373 001374 002733 000142 000142 000144 000146 000148 000106 000776 003047 Also contains many bland fields below, but I am not sure if + they wil +l show up on the question.
Please help me. I don't understand his statement and how to achieve it. Any help would be appreciated.
Prince99

too much is never enough...

Replies are listed 'Best First'.
Re: Help with arrays/sub procedures
by stephen (Priest) on Apr 11, 2001 at 02:30 UTC

    What gryphon and Trimbach say is, as usual, true. Unfortunately, figuring out precisely what your boss wants is something you'll have to do yourself. Here's an idea on how to make the program more flexible.

    First, extract out your parsing subroutine into a separate subroutine that reads a line of your program and returns a hash. (We'll cover that in a second.) So, your reading loop can look like this:

    Disclaimer: All code untested.

    my @claim_records = (); while (<CLAIMS>) { push(@claim_records, read_record($_)); }

    Next, you're going to want to redo your read_record routine to use unpack() and hash references. First, you should define the template for unpack(). I tend to do these things as constants. I won't do the whole thing, just the first three fields for illustration:

    ## Put this at the top of your program ## This would be much longer in your program. use constant CLAIM_TEMPLATE => 'A8A6A2'; use constant CLAIM_KEYS => qw( claim_batch_number claim_number claim_type );
    'A8A6A2' means "The claim template line will consist of fixed-length strings, the first of whose length is 8, second six, third two". You'll need to add to this template. Ditto the CLAIM_KEYS, which we'll use to access the info later on. I put the CLAIM_KEYS up there next to them, so it's easier to keep them in the same order. Then, you can have read_record do this:
    sub read_record { my ($line) = @_; my %claim_record = (); @claim_record{ CLAIM_KEYS } = unpack(CLAIM_TEMPLATE, $line); return \%claim_record; }
    What this does: first it creates an empty hash, %claim_record. Then it unpacks the fixed-length strings in that line of the template record, and assigns the first record to 'claim_batch_number', the second to 'claim_number', etc. Then it returns a reference to the %claim_record hash to our main routine, where it's stored in an array.

    Now, if you want to sort these guys, you have an easier time. Just remember that you can define your own comparison routine for sort:

    my $sort_by = 'claim_type'; foreach $record ( sort sub { $a->{$sort_by} cmp $b->{$sort_by} } @clai +m_records ) { print STDOUT $record->{'claim_number'}, "\n"; }

    That way, you can change what you sort on by changing $sort_by.

    I haven't had a chance to test this, so corrections are encouraged. Best of luck.

    stephen

      BTW the file format was supposed to be line sequential, but instead came in a one long line of data. That is why I had to do the following:
      $x = $_;#Take in the whole line while(length($x gt 0)) { $_ = substr($x, 0, 434);#pull out the first 434 + characters. $x = substr($x, 434);#put the rest of the line back + into $x. $_ = " ".$_;#added a space to the beginning so I + could still +use the same file format from position 1.
      Thanks

      Prince99

      Too Much is never enough...
      I greatly appreciate your help. Not just the fact that you threw some code up there, but the fact that you explained it so that I finally can look at using a hash and not have a brain embylism(sp). The only thing I am not sure about is how to find the associated fields once the first field has been sorted. Again, you have been very helpful.
      Thanks

      Prince99

      Too Much is never enough...
Re: Help with arrays/sub procedures
by Trimbach (Curate) on Apr 11, 2001 at 01:54 UTC
    I'm not entireley certain what the problem is, all in all, especially without a sample data file to see what's going on. I can say, however, that it appears that CLAIMS is comprised of fixed-length records, seeing as how you're doing a whole lot of substr to pick the file apart character by character.

    In a case like this you really, really, REALLY want to use unpack. Trust me on this one... the pack/unpack functions were born to handle fixed-length strings like what you have. unpack will slice through your data like a hot knife through butter, it will leap the tallest buildings in a single bound, it will guarantee your promotion and buy you a nice house in the country. Read up on it and become enlightened.

    Gary Blackburn
    Trained Killer

Re: Help with arrays/sub procedures
by gryphon (Abbot) on Apr 11, 2001 at 01:17 UTC

    Greetings Prince99,

    Couple of things: First off, I think you'll want to use a hash instead of a series of arrays to hold your data. But either way, I think the ultimate goal is to be able to print a report of the data or perhaps a subsection of the fields sorted by one of the fields (say the claim # for example). Right?

    Can you post up a small section of example data in the format you'll be using? Also, let me/us know exactly what you want the "report" to look like. It should be a fairly simple thing to then build a script to put the data where you want it. :)

    -gryphon