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

ok, i'm very confused here. i've hacked this script together and now i'm totally lost.

#!/usr/bin/perl ##BILLING PROGRAM## ##open needed files to use in program open(FILE, "../Counts/data.txt"); open(FILE2, "../Counts/file.csv"); ##throw files into arrays and define arrays @data = <FILE>; @data2 = <FILE2>; ##define hash my %keyhash = ( $id => { NAME => $name, SRID => $srid, CSV => [] } ); ##populate arrays: for ( @data ) { ##define variables my ($id,$name,$srid) = split /,/; # Add some error checking to make sure the # hash key $id does not already exist $keyhash{$id} = { NAME => $name, SRID => $srid, CSV => [], } } ##print unused ids from csv file print "\n\nUnused ids from csv file\n"; print "--------------------------\n"; for ( @data2 ) { my ($id,$name,$srid) = split /,/; # Warn and do nothing if a record is found for which the # $name is not already in %keyhash unless ( defined( $keyhash{$name} ) ) { warn "No such record $id!\n"; next; } push @{$keyhash{$id}{CSV}}, [ $name, $srid ]; } ##Finally, extract the number of records for each customer ##print column headers print "\n\n"; print "Customer #of docs\n"; print "-------------------------\n"; # A little something to get the plurality correct for ( keys %keyhash ) { my $num = @{$keyhash{$_}{CSV}}; printf "%s %d\n", $keyhash{$_}{NAME}, $num, } ##just formatting by adding a couple returns at the end of the printou +t print "\n\n"; ##my choice of data structures ( hashes instead of arrays ) is dependa +nt ##on how we want to use the data later. ##so far this hash is working fine unless I figure out a better way ##close files close FILE; close FILE2; ##exit program exit;


Here's what I'm trying to do:

1-print the customer name (field2) from @data.
2-count the number of times srid appeared in @data2 and print out next to customer name from @data.
3-print all srids in @data2 that didn't match with any srids in @data.


Thanks.

Replies are listed 'Best First'.
Re: still confused!
by dws (Chancellor) on Mar 24, 2001 at 02:23 UTC
    The path ahead will be much smoother if you
    1. use strict;
    2. Check system calls (like open) for failures
    3. Don't prime %keyhash with a bogus entry
    4. chomp(@data = <FILE>); to remove "\n" from the SRIDs (on the assumption that you're going to use them at some point as the script evolves)
    5. store your SRIDs consistently. (What you're pushing onto %keyhash isn't consistent with how you claim to be laying that structure out.
Re: still confused!
by ColonelPanic (Friar) on Mar 24, 2001 at 02:31 UTC
    You need to give a little more information. What kinds of error messages are you getting? What does the output look like?

    Here are some suggestions, though:

    When you open files, always use error handling:
    open (FILE, "file.txt") or die "Can't open file: $!";

    You are wasting a ton of memory by loading the files into arrays completely. instead, use a loop like this:
    while (<FILE>) { #put stuff in the hash here }
    Then, as soon as you are done with a file, it is good practice to close it.

    Those lines that define the keyhash aren't doing what you expect. They are just adding erroneous elements to keyhash. Perl will automatically add whatever you tell it to, there's no need to tell it what to expect.

    Don't use for to loop through an array. Use foreach. While for will work the same most of the time, it can bite you.

    You should probably read the perlref and perllol man pages to learn how to use complex data structures. While you're almost there, you make some errors. For example,
    $hashref{$_}{CSV}; should be ${$hashref{$_}}{CSV};
    I know this can get confusing, I've messed it up plenty of times myself.



    When's the last time you used duct tape on a duct? --Larry Wall
      Actually for and foreach really are identical, though the latter looks better in this case.

      --
      I'd like to be able to assign to an luser

      I made the modifications as you suggested. I'm getting the following errors.

      Global symbol "@data" requires explicit package name at ./billing.pl l +ine 16. Global symbol "@data2" requires explicit package name at ./billing.pl +line 17. Global symbol "$id" requires explicit package name at ./billing.pl lin +e 21. Global symbol "$name" requires explicit package name at ./billing.pl l +ine 21. Global symbol "$srid" requires explicit package name at ./billing.pl l +ine 22. Global symbol "@data" requires explicit package name at ./billing.pl l +ine 29. Global symbol "@data2" requires explicit package name at ./billing.pl +line 48. Execution of ./billing.pl aborted due to compilation errors.


      But the script still isn't in shape enough to do what I need it to do, right?!
        Actually I fixed that mess. Now when I run the script, I get the following:

        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!
        No such record ZZ!

        The script is reading the wrong field..ZZ is being pulled from the first field, I need the second field to be looked at. Also, it looks as if it's looping through over and over. Any suggestions?

        Thanks.