http://qs321.pair.com?node_id=520674

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

Hello Monks, I want to do something that I am not sure I am able to do, so any help would be appreciated. A brief summary of what I think I want to do: I have a file I want to load into a hash table, this is just a plain csv file, with either a BLANK or an X in its fields. Why? I have a script that needs to determine if the hash field is something I want to turn off. I could use a multi dimenisonal array, but it would be more clear to other developers if I could use a Hash to represent the name of what I want to turn off. I tried to create and initialize the hash table like this:
%HashTempRec = ( 'Name' => '', 'AlarmConsistencyMgr' => '', 'AlarmForwarder' => '', 'AlarmForwarderServer' => '', 'alert_publisher' => '', 'AnalogGatewayMain' => '', 'AssetTracking' => '', 'CallerPosition' => '', );
There are more fields, but for readability I've removed them. So now when I read the csv file, ace.dll,,,X,X,,X,X,X,X,X,X,X,,,,,,,X,X,X,,,,X,,,,,,,,X,,,,,X,,, -- there are more records, but I want to keep this post reasonable. I want to populate the Hash Table with the elements from this file. So I tried to do
for each $item (@Dependency) { @HashTempRec = $item; }
This obvisuouly fails and I don't know where to go from here. Is there a way to load a hash table is this fashion?
--Hash table definiion here-- $Test1 = "D:\\Profiles\\p57571\\Desktop\\Book3.csv"; if( -e $Test1) { print "Opening $Test1\n"; open(PACKAGEINPUT, "<$Test1"); my(@lines) = <PACKAGEINPUT>; foreach $temp(@lines) { chomp $temp; if( $temp =~ m/\S/ig) { #find the extension my $fileExt = substr( $temp, -3 ) ||''; #this searches for exe's then any coresponding dlls + if( $fileExt eq 'exe' ) { foreach my $element( split /,/, $temp) { if( $element =~ m/\.exe/) { #print "element = $element\n"; } } } else { print "temp = $temp\n"; %HastTempRec = $temp; } } } } else { print "$Test1 does not exist\n"; }
thanks in advance. I hope my question and reasons why are clear enough.

Replies are listed 'Best First'.
Re: Loading a hash table
by idsfa (Vicar) on Jan 03, 2006 at 17:47 UTC

    Use Text::xSV:

    use Text::xSV; my $csv = Text::xSV->new( filename => "foo.csv", header => \@column_names, ); while ($csv->get_row()) { # You could use fetchrow_hash here, but I'll just print a message # If you want a HoH or AoH, read up on extract_hash my ($name, $alert_publisher) = $csv->extract(qw(Name alert_publisher +)); print "Dll: $name\t is " . (($alert_publisher eq 'X')? '' : 'not ') . "an alert publisher\n"; }

    It's worth noting that your problem as posed overwrites the hash each time you read in a new line. If this is not what you want, you need to construct an array (or a hash) of hashes ... see the comment for pointers.


    The intelligent reader will judge for himself. Without examining the facts fully and fairly, there is no way of knowing whether vox populi is really vox dei, or merely vox asinorum. — Cyrus H. Gordon
Re: Loading a hash table
by TedPride (Priest) on Jan 03, 2006 at 20:19 UTC
    Assuming the format is the way you say it is, the following should work fine:
    use strict; use warnings; my @keys = ( 'Name', 'AlarmConsistencyMgr', 'AlarmForwarder', 'AlarmForwarderServer', 'alert_publisher', 'AnalogGatewayMain', 'AssetTracking', 'CallerPosition', ); $_ = <DATA>; chomp; my @vals = split /,/; my %hash; @hash{@keys} = @vals; for (@keys) { print "$_ -> $hash{$_}\n"; } __DATA__ ,,,X,X,,X,X,X,X,X,X,X,,,,,,,X,X,X,,,,X,,,,,,,,X,,,,,X,,,
    Your problem was that hash keys are not stored in the order they're specified, so your initialization order had nothing to do with the order in which the values were assigned. You have to use an array to preserve order.
Re: Loading a hash table
by smokemachine (Hermit) on Jan 03, 2006 at 22:17 UTC
    Almost the same, but...
    perl -ne 'BEGIN{$\="\n"; @keys = qw / Name AlarmConsistencyMgr AlarmForwarder AlarmForwarderServer alert_publisher AnalogGatewayMain AssetTracking CallerPosition /} @array=split /,/;END{@hash{@keys}=@array;print "$_ -> $hash{$_}" forea +ch(keys %hash)}' ace.dll