tags:

views:

355

answers:

3

I have a csv with the first column a label followed by comma separated values:

LabelA,45,56,78,90
LabelB,56,65,43,32
LabelC,56,87,98,45

I'd like the first column (LabelA etc) to be the Key in a hash with the numeric values in an array.

I can read the file into an array or scalar but I'm not sure what to do after that. Suggestions??

Edit: Ok, so it looks like this assigns the value to a key ..but what about the comma delimited numbers in my example? Where are they going? Are they in %hash ? If so could you maybe dumb down your explanation even further? Thanks.

+1  A: 

See perlfunc split and perldsc.

  1. Read each line.
  2. Chomp it.
  3. Split it on commas.
  4. Use the first value in the result as the key to your HoA.
  5. The other values become the array.
  6. Store a ref to the array in the hash under the key.
  7. ...
  8. Profit!!!

Make a hash of array references:

Your data structure should look like this:

my %foo = (
    LabelA => [  2, 3,  56, 78, 90 ],
    LabelB => [ 65, 45, 23, 34, 87 ],
    LabelC => [ 67, 34, 56, 67, 98 ],
);
daotoad
+1  A: 

Well, let's assume that there are no special characters and so on.

First you open the file:

open my $fh, '<', 'some.file.csv' or die "Cannot open: $!";

Then you read from it in loop:

while (my $line = <$fh>) {

Afterwards, you remove trailing white characters (\n and others):

$line =~ s/\s*\z//;

And split it into array:

my @array = split /,/, $line;

When it's in array, you get first element off the array:

my $key = shift @array;

And store it in hash:

$hash{$key} = \@array;

(\@array means reference to array).

Whole code:

my %hash;
open my $fh, '<', 'some.file.csv' or die "Cannot open: $!";
while (my $line = <$fh>) {
  $line =~ s/\s*\z//;
  my @array = split /,/, $line;
  my $key = shift @array;
  $hash{$key} = \@array;
}
close $fh;
depesz
Ok, so it looks like this assigns the value to a key ..but what about the comma delimited numbers in my example? Where are they going? Are they in %hash ? If so could you maybe dumb down your explanation even further? Thanks.
RH
Well, this line: $hash{$key} = \@array; puts the values in hash. You can add: use Data::Dumper; print Dumper(\%hash); at the end of program to see how the data structure looks.
depesz
+6  A: 

Personally, I like the Text::CSV_XS and IO::File module:

use Text::CSV_XS;
use IO::File;

# Usage example:
my $hash_ref = csv_file_hashref('some_file.csv');

foreach my $key (sort keys %{$hash_ref}){
   print qq{$key: }
   print join q{,}, @{$hash_ref->{$key}};
   print qq{\n};
}

# Implementation:
sub csv_file_hashref {
   my ($filename) = @_;

   my $csv_fh = IO::File->new($filename, 'r');
   my $csv = Text::CSV_XS->new ();

   my %output_hash;

   while(my $colref = $csv->getline ($csv_fh))
   {
      $output_hash{shift @{$colref}} = $colref;
   }

   return \%output_hash;
}
Todd Gardner