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

I am trying to create a hash of arrays from a file. I've put the file into an array and then I'm going through the array element by element. For each element I assign a value to a variable that I would like to add as a new key in a hash. I also create an array from the element that I'd like to use as the value for the hash. So for each element in the array, I want to add a new key and value pair to the hash.

Here's what I am using:
open (BINFILE, $binaryfile) or die "Cannot open $binaryfile\n"; my @lines; while (<BINFILE>) { push (@lines, $_); } my %bin_file_data = (); for (@lines) { my @split = split (',', $_); my $sampname = $split[0]; my $binnumbers = $split[1]; my @bindata = split ('\t', $binnumbers); #I want $sampname as the key associated with the array @bindata $bin_file_data{$sampname} = @bindata; } print Dumper (\%bin_file_data); close BINFILE;

My Data Dump is giving me something like this (simplified):

$VAR1 = { 'sampname1' => 1032, 'sampname2' => 1032, };

1032 is the number of elements in @bindata. Am I just using DataDumper incorrectly or am I making an error in creating my hash?

Replies are listed 'Best First'.
Re: Creating Hash of Arrays
by kennethk (Abbot) on Sep 09, 2015 at 22:37 UTC
    You are getting bit by context: $bin_file_data{$sampname} is a scalar, and an array in scalar context returns the length of the array. What you mean to do is store a reference to an array:
    $bin_file_data{$sampname} = \@bindata;
    See perlref, perlreftut and/or perllol for more guidance.

    #11929 First ask yourself `How would I do this without a computer?' Then have the computer do it the same way.

      Thanks!

      Or

      $bin_file_data{$sampname} = [split '\t',$binnumbers];
      Dum Spiro Spero
Re: Creating Hash of Arrays
by stevieb (Canon) on Sep 09, 2015 at 22:41 UTC

    When you assign an array to a scalar like you have below, it assigns the number of elements as you've found.

    $bin_file_data{$sampname} = @bindata;

    What you want to do is stuff a reference to the array as the value to the key:

    $bin_file_data{$sampname} = \@bindata; # a different way that copies @bindata as opposed # to taking a direct reference to it @{ $bin_file_data{$sampname} } = @bindata;

    Then:

    # use the whole array for (@{ $bin_file_data{$sampname} }){ ... } # get a single element my $thing = $bin_file_data{$sampname}->[0];

    -stevieb