Perl - 需要将列值存储到散列中
Perl - need to store the column values into hash
我想在 Perl 中创建一个散列,其中 header 列作为散列键,列值作为散列值。
例如,如果我的 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 ...
因此,只需使用 header 名称,我就可以使用该列值。
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";
但我想对所有 column.I 猜测数组哈希将是最佳解决方案,但我不知道如何实现它。
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;
注意:这两者都将有效地忽略没有 headers 的任何额外列。 (并且会被重复的列名弄糊涂)。
另一个使用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
我想在 Perl 中创建一个散列,其中 header 列作为散列键,列值作为散列值。
例如,如果我的 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 ...
因此,只需使用 header 名称,我就可以使用该列值。 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";
但我想对所有 column.I 猜测数组哈希将是最佳解决方案,但我不知道如何实现它。
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;
注意:这两者都将有效地忽略没有 headers 的任何额外列。 (并且会被重复的列名弄糊涂)。
另一个使用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