FranceMadrid
FranceMadrid

Reputation: 95

How to load a CSV file into a perl hash and access each element

I have a CSV file with the following information seperated by commas ...

Owner,Running,Passing,Failing,Model
D42,21,54,543,Yes
T43,54,76,75,No
Y65,76,43,765,Yes

I want to open this CSV file and place its containments inside of a perl hash in my program. I am also interested in the code needed to print a specific element inside of the has. For example, how I will print the "Passing" count for the "Owner" Y65.

The code I currently have:

$file = "path/to/file";

open $f, '<', $files, or die "cant open $file"

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

#inside here I am trying to take the containments of this file and place it into a hash. I have tried numerous ways of trying this but none have seemed to work. I am leaving this blank because I do not want to bog down the visibility of my code for those who are kind enough to help and take a look. Thanks.

}

AS well as placing the csv file inside of a hash I also need to understand the syntax to print and navigate through specific elements. Thank you very much in advance.

Upvotes: 1

Views: 2508

Answers (2)

Shawn
Shawn

Reputation: 52419

Since it's not really clear what "load a CSV file into a perl hash" means (Nor does it really make sense. An array of hashes, one per row, maybe, if you don't care about keeping the ordering of fields, but just a hash? What are the keys supposed to be?), let's focus on the rest of your question, in particular

how I will print the "Passing" count for the "Owner" Y65.

There are a few other CSV modules that might be of interest that are much easier to use than Text::CSV:

  • Tie::CSV_File lets you access a CSV file like a 2D array. $foo[0][0] is the first field of the first row of the tied file.

So:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use Tie::CSV_File;

my $csv = "data.csv";
tie my @data, "Tie::CSV_File", $csv or die "Unable to tie $csv!";
for my $row (@data) {
  say $row->[2] and last if $row->[0] eq "Y65";
}
  • DBD::CSV lets you treat a CSV file like a table in a database you can run SQL queries on.

So:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use DBI;

my $csv = "data.csv";
my $dbh = DBI->connect("dbi:CSV:", undef, undef,
                       { csv_tables => { data => { f_file => $csv } } })
  or die $DBI::errstr;
my $owner = "Y65";
my $p = $dbh->selectrow_arrayref("SELECT Passing FROM data WHERE Owner = ?",
                                 {}, $owner);
say $p->[0] if defined $p;
  • Text::AutoCSV has a bunch of handy functions for working with CSV files.

So:

#!/usr/bin/perl
use warnings;
use strict;
use feature qw/say/;
use Text::AutoCSV;

my $csv = "data.csv";
my $acsv = Text::AutoCSV->new(in_file => $csv) or die "Unable to open $csv!";
my $row = $acsv->search_1hr("OWNER", "Y65");
say $row->{"PASSING"} if defined $row;

This last one is probably closest to what I think you think you want.

Upvotes: 0

H&#229;kon H&#230;gland
H&#229;kon H&#230;gland

Reputation: 40758

Here is an example of how to put the data into a hash %owners and later (after having read the file) extract a "passing count" for a particular owner. I am using the Text::CSV module to parse the lines of the file.

use feature qw(say);
use open qw(:std :utf8);  # Assume UTF-8 files and terminal output
use strict;
use warnings qw(FATAL utf8);
use Text::CSV;

my $csv = Text::CSV->new ( )
  or die "Cannot use CSV: " . Text::CSV->error_diag ();
my $fn = 'test.csv';
open my $fh, "<", $fn
  or die "Could not open file '$fn': $!";
my %owners;
my $header = $csv->getline( $fh );  # TODO: add error checking 
while ( my $row = $csv->getline( $fh ) ) {
    next if @$row == 0; # TODO: more error checking
    my ($owner, @values) = @$row;
    $owners{$owner} = \@values;
}
close $fh;

my $key = 'Y65';
my $index = 1;
say "Passing count for $key = ", $owners{$key}->[$index];

Upvotes: 1

Related Questions