0

I'm reading from a CSV file and populating a Hash based on Key-Value Pairs. The First Column of the record is the key, and the rest of the record is the value. However, for some file I need to make first 2 columns as Key and the rest of the record is value. I have written it as below based on if loop by checking the number of Key Columns, but I wanted to know if there is any better way to do this?

use strict;
use warnings;

open my $fh, '<:encoding(utf8)', 'Sample.csv'
      or die "Couldn't open Sample.csv";
my %hash;     
my $KeyCols=2;
    while (<$fh>) {
        chomp;
        if ($KeyCols==1) {
        next unless /^(.*?),(.*)$/;
        $hash{$1} = $2;
        }
        elsif ($KeyCols==2) {
        next unless /^(.*?),(.*?),(.*)$/;
        $hash{$1.$2} = $3;
        }
    }
toolic
  • 57,801
  • 17
  • 75
  • 117
Vinoth Karthick
  • 905
  • 9
  • 27

2 Answers2

3

Here is one way to allow for any number of key columns (not just 1 or 2), but it uses split instead of a regex:

use warnings;
use strict;

my %hash;     
my $KeyCols = 2;
while (<DATA>) {
    chomp;
    my @cols = split /,/, $_, $KeyCols+1;
    next unless @cols > $KeyCols;
    my $v = pop @cols;
    my $k = join '', @cols;
    $hash{$k} = $v;
}

__DATA__
a,b,c,d,e,f
q,w,e,r,t,y

This is a self-contained code example.


A big assumption is that your CSV file does not contain commas in the data itself. You should be using a CSV parser such as Text::CSV anyway.

toolic
  • 57,801
  • 17
  • 75
  • 117
1

Perhaps it is better to define variables at first lines of the code -- otherwise you have to jump all over the code.

You can define regex based on your $KeyCols and processing code will be same as before.

use strict;
use warnings;
use feature 'say';

my $KeyCols = 2;
my $fname   = 'Sample.csv';

my %hash;
my $re;

if( $KeyCols == 2 ) {
    $re = qr/^(.*?,.*?),(.*)$/ 
} else {
    $re = qr/^(.*?),(.*)$/;
}

open my $fh, '<:encoding(utf8)', $fname
      or die "Couldn't open $fname";

while (<$fh>) {
    chomp;
    next unless /$re/;
    $hash{$1} = $2;
}

close $fh;
Polar Bear
  • 6,762
  • 1
  • 5
  • 12