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

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

Dear Monks,

I have a working script and looking ways to improve the code . I came across a line which splits the CSV file to get the values. This line is very long becaus around 100 variables are specified for each of the splitted element from CSV file and is hard to maintain. The code is :
use strict; use warnings; my $file = "/tmp/index.csv"; open (FL, "< $file"); while ($line = <FL>){ my ($country, $exchange, $name, $forex, $ric, $isin, $cusip) = +split(/\;/ $line); #similarly 100 vars are declared }
CSV file format:
##CSV file format Country;Exchange;NAME;Forex;RIC;ISIN;CUSIP; AT;XETRA (AT) ;RAIFFEISEN INTERNATIONAL BANK ;EUR;RIBH.VI +;AT0000606306; ;B0704T9; AT;XETRA (AT) ;IMMOEAST IMMOBILIEN ANLAGEN AG;USD;IMEA.VI +;AT0000642806; ;
The first line of the CSV is the header. Using map function I want to dynamically assign the splitted values to the variables given in the header of CSV (Country;Exchange;NAME;Forex;RIC;ISIN;CUSIP;). i.e the final output should look like:
$Country = "AT"; $Exchange ="Xetra (AT)"; $NAME = "RAIFFEISEN INTERNATIONAL BANK "; #etc..
I'd like some suggestions on how to dynamically map the splitted values in the above way.

Replies are listed 'Best First'.
Re: Dynamically map the elements of CSV
by Tanktalus (Canon) on May 29, 2006 at 15:11 UTC

    Personally, I wouldn't load it. I'd grab DBI and DBD::CSV and interrogate it as if it were a database. And then, if that were too slow for some reason, I'd actually put it in a database (using the same DBD::CSV for import) - perhaps a temporary table, and query the database.

    That said, thus far, I've not had to move off DBD::CSV - it is fast enough for my purposes.

Re: Dynamically map the elements of CSV
by izut (Chaplain) on May 29, 2006 at 14:30 UTC
    I think this is what you want:
    my @entries; my @keys; while ($_ = <DATA>) { if ($. == 0) { # first line @keys = split /;/; next; } my %data; $data{@keys} = split/;/; push @entries, \%data; }

    Update: updated some code errors.

    Igor 'izut' Sutton
    your code, your rules.

Re: Dynamically map the elements of CSV
by BrowserUk (Patriarch) on May 29, 2006 at 14:38 UTC

    Split the header line into an array before entering the loop, and then use that to build an AoHs:

    use strict; use warnings; my $file = "/tmp/index.csv"; open (FL, "< $file"); my @fieldnames = split ';', <FL>; ## my @data; while ($line = <FL>){ my %temp; @temp{ @fieldnames } = split ';', $line; push @data, \%temp; } ## print the 'Forex' field of the 124th line (array runs from 0). print $data[ 123 ]{ Forex };

    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    Lingua non convalesco, consenesco et abolesco. -- Rule 1 has a caveat! -- Who broke the cabal?
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.
Re: Dynamically map the elements of CSV
by CountZero (Bishop) on May 29, 2006 at 19:33 UTC
    Tie::Handle::CSV makes it all automatic: it reads the header line and makes the hash for you.

    From the docs:

    Tie::Handle::CSV makes basic access to CSV files easier. When you read from the file handle, a hash reference or an array reference is returned depending on whether headers exist or do not.
    Regardless of the type of the returned data, when it is converted to a string, it automatically converts back to CSV format.

    CountZero

    "If you have four groups working on a compiler, you'll get a 4-pass compiler." - Conway's Law

Re: Dynamically map the elements of CSV
by tcf03 (Deacon) on May 29, 2006 at 15:00 UTC
    I once had a similar problem I was working on, and had the idea to pus it all into hash ( build hash from csv file ) I received some advice which ultimatley helped me out - such as using some existing modules which were tried and tested as opposed to rolling my own...Good Luck...

    Ted
    --
    "That which we persist in doing becomes easier, not that the task itself has become easier, but that our ability to perform it has improved."
      --Ralph Waldo Emerson