0

I have a Problem with converting the following snippet of a csv into a hash using Perl.

emp_no,birth_date,first_name,last_name,gender,hire_date
10001,1953-09-02,Georgi,Facello,M,1986-06-26
10002,1964-06-02,Bezalel,Simmel,F,1985-11-21
10003,1959-12-03,Parto,Bamford,M,1986-08-28
10004,1954-05-01,Chirstian,Koblick,M,1986-12-01
10005,1955-01-21,Kyoichi,Maliniak,M,1989-09-12

The Hash should look like:

$employee = {
emp_no=>[10001,10002,10003,10004,10005],
birth_date=>[1953-09-02,1964-06-02,1959-12-03],
simarly for fistname , lastname and hire_date

}

I have tried like this

while(<FH>){


    @keys = split /,/,$_ if $.==1;  #for the first line 

       @row = split /,/,$_;

          push @hash{@keys},@row;

}
7
  • 1
    What's your question? If you're having trouble getting your script to work, please show what you've tried. Commented Jun 25, 2013 at 19:00
  • 5
    Wouldn't it be better to convert it into an array of hashes instead of a hash of arrays? Commented Jun 25, 2013 at 19:01
  • See search.cpan.org/~makamaka/Text-CSV-1.32/lib/Text/CSV.pm for a package for processing CSV files. Commented Jun 25, 2013 at 19:02
  • @Barmar - it's better to link to non-versioned CPAN links (found under "Permalink" name on top right corner of CPAN's page). Commented Jun 25, 2013 at 19:07
  • 2
    metacpan links are even better :-) metacpan.org/module/Text::CSV Commented Jun 25, 2013 at 19:24

3 Answers 3

2

Use this only if you for some reason can't use http://metacpan.org/pod/Text::CSV module :)

my %employee;
while (<ARGV>)) {
  next if /^emp/;
  my @r = split/,/; 
  push @{$employee{$_}}, shift @r 
       for qw(emp_no birth_date first_name last_name gender hire_date);   
}
Sign up to request clarification or add additional context in comments.

Comments

1

Something like:

while ( my $line = readline($fh) ) {
    chomp $line;
    my ( $emp_no, $birth_date, $first_name, $last_name, $gender, $hire_date ) = split /,/, $line;
    push @{ $employee->{emp_no} }, $emp_no;
    #etc.
}

Comments

0

Text::CSV will store your data as an array of hashes with each hash key being the column name. This seems to make the most sense. For example:

my %employee =  %{ $employee_array[2] };  #Row #3 of your file:
print "The name of the third employee is $employee{first_name} $employee{last_name}\n";

Thus, a single row of your array contains all of the data for that employee.

In your case, you'd have to keep the index the same across multiple arrays:

print "The name of the third employee is $first_name[2] $last_name[2]\n";

If you had a function that operated on the employee, you'd have to pass all of your arrays to the function:

print_paycheck($first_name[1], $last_name[1], $employee_num[1], $hire_date[1]...);

While if you had an array of hashes, you could do this:

print_paycheck($employee_array[1]);

I take it that you don't know about references. Many beginner Perl books don't discuss them, and they're not an obvious extension of Perl. However, references allow you to make these more complex data structures. Fortunately, Perldoc has an excellent Tutorial. I suggest that you read it.

In reality, you probably want to to store your data keyed by the employee number, so you want a hash of hashes.

Here's an example of a hash of hashes. NOTE: This is not the way I'd do the program. First, I would use Text::CSV if available, and then I would actually use an object oriented approach. However, I wanted to keep this as a simple hash of hashes:

use warnings;
use strict;
use feature qw(say);

use Data::Dumper;

my %employee_hash;
<DATA>;  #Field Names
while ( my $employee_data = <DATA> ) {
    chomp $employee_data;
    my ($employee, $birth_date, $first_name, $last_name, $gender, $hire_date) = split /,/, $employee_data;
    $employee_hash{$employee}->{birth_date} = $birth_date;
    $employee_hash{$employee}->{first_name} = $first_name;
    $employee_hash{$employee}->{last_name}  = $last_name;
    $employee_hash{$employee}->{gender}     = $gender;
    $employee_hash{$employee}->{hire_date}  = $hire_date;
}

for my $employee ( sort keys %employee_hash ) {
    my $gender;
    if ( $employee_hash{$employee}->{gender} eq "M" ) {
        $gender = "he";
    }
    else {
        $gender = "she";
    }

    printf qq(Employee: %s is %s %s and %s was hired on %s\n),
        $employee,
        $employee_hash{$employee}->{first_name},
        $employee_hash{$employee}->{last_name},
        $gender,
        $employee_hash{$employee}->{hire_date};
}

__DATA__
emp_no,birth_date,first_name,last_name,gender,hire_date
10001,1953-09-02,Georgi,Facello,M,1986-06-26
10002,1964-06-02,Bezalel,Simmel,F,1985-11-21
10003,1959-12-03,Parto,Bamford,M,1986-08-28
10004,1954-05-01,Chirstian,Koblick,M,1986-12-01
10005,1955-01-21,Kyoichi,Maliniak,M,1989-09-12

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.