Perl - 需要将列值存储到哈希中

时间:2015-03-18 10:31:48

标签: perl hash

我想创建一个散列,其中列标题为散列键,列值为Perl中的散列值。

例如,如果我的csv文件包含以下数据:

A,B,C,D,E 
1,2,3,4,5
6,7,8,9,10
11,12,13,14,15 ...

我想创建一个哈希,如下所示:

A=> 1,6,11
B=>2,7,12
c=>3,8,13 ...

因此,只需使用标题名称,我就可以使用该列值。 PERL有办法做到这一点吗?请帮帮我。

我能够使用以下脚本将所需的列值存储为数组

use strict;
use warnings;

open( IN, "sample.csv" ) or die("Unable to open file");
my $wanted_column = "A";
my @cells;
my @colvalues;

my $header       = <IN>;
my @column_names = split( ",", $header );
my $extract_col  = 0;

for my $header_line (@column_names) {
    last if $header_line =~ m/$wanted_column/;
    $extract_col++;
}
while ( my $row = <IN> ) {
    last unless $row =~ /\S/;
    chomp $row;
    @cells = split( ",", $row );
    push( @colvalues, $cells[$extract_col] );
}
my $sizeofarray = scalar @colvalues;
print "Size of the coulmn= $sizeofarray";

但是我想对我的所有专栏做这个。我猜数组的哈希将是最好的解决方案,但我不知道如何实现它。

2 个答案:

答案 0 :(得分:2)

对于这类事情,

Text::CSV是一个有用的辅助模块。

use strict;
use warnings;

use Text::CSV;
use Data::Dumper;

my %combined;
open( my $input, "<", "sample.csv" ) or die("Unable to open file");
my $csv = Text::CSV->new( { binary => 1 } );
my @headers = @{ $csv->getline($input) };

while ( my $row = $csv->getline($input) ) {
    for my $header (@headers) {
        push( @{ $combined{$header} }, shift(@$row) );
    }

}
print Dumper \%combined;

由于您没有使用模块请求 - 可以使用split,但您需要牢记这些限制。 CSV格式允许嵌套在引号中的逗号。 split不能很好地处理这个案子。

use strict;
use warnings;

use Data::Dumper;

my %combined;
open( my $input, "<", "sample.csv" ) or die("Unable to open file");
my $line = <$input>;
chomp ( $line );
my @headers = split( ',', $line );

while (<$input>) {
    chomp;
    my @row = split(',');
    for my $header (@headers) {
        push( @{ $combined{$header} }, shift(@row) );
    }

}
print Dumper \%combined;

注意:这两个都会有效地忽略任何没有标题的额外列。 (并且会因重复的列名而感到困惑)。

答案 1 :(得分:1)

使用for循环的另一种解决方案:

use strict;
use warnings;

my %data; 
my @columns; 

open (my $fh, "<", "file.csv") or die "Can't open the file : ";

while (<$fh>)
{
    chomp;
    my @list=split(',', $_);
    for (my $i=0; $i<=$#list; $i++)
    {
        if ($.==1)  # collect the columns, if its first line.
        {
            $columns[$i]=$list[$i];
        }
        else        #collect the data, if its not the first line. 
        {
            push @{$data{$columns[$i]}}, $list[$i];
        }
    }
}
foreach (@columns)
{
    local $"="\,";
    print "$_=>@{$data{$_}}\n";
}

输出将如下:

A=>1,6,11
B=>2,7,12
C=>3,8,13
D=>4,9,14
E=>5,10,15