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

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

So, I've read over explanations on making a hash of arrays and attempted to adopt the methods into a program to take a simple datafile and turn it into a hash of arrays. The file has the format
1,2 1,3 1,4 2,3 2,5 2,5
And I want to make a hash of arrays where the first column is the key and the second column is the data. I've done it like so:
local %DATAHASH; open (DATA, 'foo.csv'); while (<DATA>){ chomp; my @datarow=split(/,/, $_); push(@{$DATAHASH{$datarow[0]}}, ($datarow[1])); }
And yet, whenever I try and print out the contents of DATAHASH, either after the while loop or in its midst using Dumper($DATAHASH}, I get a $VAR1 = undef Any advice on remedying this situation? And looking further down the line, for something that will have two seperate keys (e.g. 1,2,3 is a line from the file) I'm using push( @{$DATAHASH{$datarow[0]}->{$datarow[1]}}, ($datarow[2]) );, which I'm assuming I'll just modify in the same way.

Replies are listed 'Best First'.
Re: Making a hash of arrays from a datafile
by borisz (Canon) on Oct 19, 2004 at 22:10 UTC
    Your example look fine, just use print Dumper(\%DATAHASH);. and use my instead of local until you know the difference.
    Boris
      *slaps self in head* right, of course. That's why the Dumper wasn't working. With respect to local v. my, no, I know what I'm doing here, the DATAHASH is actually declared elsewhere (I was including it here for clarity) and is referenced my multiple subroutines once the data is first read in. Also, the data will never contain commas, so I'm not too worried aobut getting bitten in the arse there. Thanks!
        I know what I'm doing here, the DATAHASH is actually declared elsewhere (I was including it here for clarity) and is referenced my multiple subroutines once the data is first read in.

        This doesn't sound like a compelling reason to use dynamically scoped package variables instead of lexicals. I hate to sound too persnickety, but it's usually advisable to use lexicals by default, and only use package variables when absolutely necessary. So far, you haven't even demonstrated a remote necessity, and your assertion that you "know what [you're] doing" isn't very convincing.

Re: Making a hash of arrays from a datafile
by allolex (Curate) on Oct 19, 2004 at 22:42 UTC

    In addition to borisz's remarks, you should probably be a little more careful with comma-separated values, which have bitten quite a few people. What happens to your data if one of your values contains a comma? Are you dealing with quotes? You can use Text::CSV to address this problem and others. Even if it doesn't apply to your test code, I hope it helps you in the future.

    --
    Damon Allen Davison
    http://www.allolex.net

Re: Making a hash of arrays from a datafile
by TedPride (Priest) on Oct 19, 2004 at 23:14 UTC
    use strict; use warnings; my %hash; m/(\d+),(\d+)/ and push(@{$hash{$1}}, $2) for <DATA>; for (sort keys %hash) { print "$_ => "; print "$_ " for sort @{$hash{$_}}; print "\n"; } __DATA__ 2,6 2,3 1,2 2,5 1,3 1,4
    This creates a hash with the first value as key and all the second values pushed into nested arrays. Sorting and printing is simple, as seen above.