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

Okay Monks, this is going to be a pretty lame question for most of you.

What I want to do is read in a complete line of a file into a hash and then use elements of that hash where I want. Example:
#!/usr/bin/perl my %ACCTS = (); open(IN, "< myfile") || die "Help!\n"; while (<IN>) { ($id, $name, $street, $city, $zip, $phone, $start_dt) = split(/\|\|/, +$_); $ACCTS{$name}{$street}{$city}{$zip}{$phone}{$start_dt}=$id; } close IN;
If I reference a foreach $key statement, I can display my id's quite nicely. But if I try to display the rest, I get some output like 13423 - HASH(0x11d4a4). What I want is to use each element in Hash when I want to. Display NAME, PHONE if I wanted to, or NAME, ADDRESS if I wanted to.

How can I do that, or is an ARRAY just the best option?

Thanks!
Louis

Replies are listed 'Best First'.
Re: How to use hashes well
by Abigail-II (Bishop) on Oct 31, 2003 at 17:19 UTC
    Where do you want to index on? The name? In that case, do something like this after the split:
    $ACCTS {$name} = {STREET => $street, CITY => $city, ZIP => $zip, PHONE => $phone, START_ID => $start_id, ID => $id};

    Abigail

      Abigail's solution is good. I have modified your code slightly to build a hash suggested by Abigail. Instead of hardcoding the hash assignment, I have created a list called col_def that holds the name of the data columns in your data, and use it to construct the hash entries dynamically.

      Note that I have added use strict and use Data::Dumper to the top of the code. Data::Dumper is one of the most handy development utility while coding hash and array structures, it dumps the data structure held in the variable. It's a good practise to include both use strict and use Data::Dumper in your code, especially when you are learning to use Perl.

      #!/usr/bin/perl -w use strict; use Data::Dumper; my @col_def = qw/ id name street city zip phone start_dt /; my %ACCTS; open(IN, "< myfile") or die "Help!\n"; while (<IN>) { chomp; # need to remove \n character, otherwise last # field will contain \n my @cols = split /\|\|/; $ACCTS{$cols[0]} = { map { $col_def[$_] => $cols[$_] } 1..$#col_def }; } close IN; print Dumper(\%ACCTS);
Re: How to use hashes well
by agh (Novice) on Oct 31, 2003 at 17:54 UTC
    How about this:
    #!/usr/bin/perl my $myfile = 'somefile'; my %by_id = (); my %by_name = (); open (IN, '<', $myfile) or die "Can't open $myfile: $!\n"; sub ID () {0} sub NAME () {1} sub STREET () {2} sub CITY () {3} sub ZIP () {4} sub PHONE () {5} sub START_DT () {6} while (<IN>) { my @f = split /\|/o; $by_id{$f[ID]} = \@f; $by_name{$f[NAME]} = \@f; # etc for other indexes you want } my $id = 'fred'; if (exists $by_id{$id}) { print "$id's Address is ", $by_id{$id}->[ADDRESS], "\n"; } else { print "I've never heard of this $id guy.\n"; }
    The idea is pretty simple: create a hash of references to arrays. Use inline functions to address the contents of the arrays (makes things more readable). If you want multiple indexes then you'd be better off using an database instead of trying to do it all in perl, but you could create a hash for each index and have them all point to the same array. I've done two, id and name, for example. Of course if your values aren't unique then you're indexes will get clobbered. Like I said, use a real database if you want to do database stuff. :)

    Advanced Perl Programming has an excellent section on datastructures in Perl, which you might want to check out. Drew

Re: How to use hashes well
by injunjoel (Priest) on Nov 01, 2003 at 01:31 UTC
    Greetings all,
    Im not sure what it is that you want but here is an option...
    #!/usr/bin/perl -w use strict; use Dumpvalue; my @ACCTS; open(IN, "< myfile") || die "Help!\n"; while (<IN>) { my ($id, $name, $street, $city, $zip, $phone, $start_dt) = split(/\|\| +/, +$_); ###push onto the array ACCTS an anonymous hash reference from the valu +es you just split. push(@ACCTS, {'name' => name, 'street' =>$street, 'city' =>$city, 'zip +' =>$zip, 'phone' =>$phone, 'start_dt' =>$start_dt, 'id' =>$id}); } close IN; ###always check what you have created. dump_ref(\@ACCTS); sub dump_ref { my $ref = shift; my $dumper = new Dumpvalue; $dumper->dumpValues($ref); }
    The above methodology will create an array of hashes. I assumed that ACCTS was probably referring to account information so a list of accounts is probably what you are looking for... though I could be wrong. So each account record is now an anonymous hash within your ACCTS array.
    This way something like
    foreach(@ACCTS){ #dereference the elements of the hash contained in this #row of your array with the arrow... its just easier to #read in my opinion. print "This accounts id is ".$_->{id}."\n"; }
    Would be how you get back at your data.
    The dump_ref sub simply shows you the internals of any nested datatype you create.
    Hope that helps.
    -injunjoel