我有一个数组的哈希。每个哈希键都是一个列名。每个数组都是该列的值。
$myHash{column1} = [value1, value2, ..., valueN];
$myHash{column2} = [value1, value2, ..., valueM];
...
每个数组的长度不同。
我想将其输出为CSV文件,每个数组均为一列。我查看了Text :: CSV,但看不到如何使该结构与该模块一起使用。
谢谢。
答案 0 :(得分:1)
使用Text::CSV_XS(或Text :: CSV,因为它们共享相同的API)很容易。只需按索引/行号遍历哈希中的数组:
my @columns = sort keys %myHash;
my $rows = scalar @{ $myHash{ $columns[0] }};
my $writer = Text::CSV_XS->new();
open my $fh, '>', 'output.csv' or die "Couldn't write file: $!";
# Output headers
$writer->print($fh, \@columns);
# Output payload
for my $row (0..$rows) {
$writer->print($fh, [map { $myHash{$_}->[$row] } @columns]);
};
修改问题后,此答案不再完全适用。如果数组的长度不同,则无法为丢失的列添加值。
答案 1 :(得分:0)
您可以分两个步骤进行操作: 1.将数组的哈希值转换为数组的数组 2.编写csv。
我的解决方案允许您使用空白列。如果您在哈希列1,3,5中定义,则列2,4将为空白。
my @twoDarray;
foreach my $row (keys %myHash) {
my ($colIndex) = $row =~ /(\d+)$/;
$colIndex--;
$twoDarray[0][$colIndex] = $row;
foreach my $rowIndex(0..$#{$myHash{$row}}) {
$twoDarray[++$rowIndex][$colIndex] = $myHash{$row}->[$rowIndex];
}
}
my $finalFile = "output.csv";
open my $OUT, ">", $finalFile;
my $csvTo = Text::CSV_XS->new ({ binary => 1, auto_diag => 2, sep_char => ',', allow_whitespace => 1, eol => "\n"});
$csvTo->print ($OUT, $_) for (@twoDarray);
close $OUT;
答案 2 :(得分:0)
如我的评论所述,问题描述不完整。我的解决方案假定:
column1
,...,column9
,column10
,依此类推,即,生成的CSV中的列应按嵌入数字进行数字排序。 / li>
#!/usr/bin/perl
use strict;
use warnings;
use List::Util qw(max);
use Text::CSV;
# read in hash-of-arrays
my %hash;
while (<DATA>) {
chomp;
my($column, @values) = split(' ');
$hash{$column} = \@values;
}
# column sort order (using Schwartzian transform)
my @column_order =
map { $_->[0] } # [ "columnN", N ] -> "columnN"
sort { $a->[1] <=> $b->[1] } # numerical sort, ascending
map { [ /^(column(\d+))$/ ] } # "columnN" -> [ "columnN", N ]
keys %hash;
# calculate highest array index
my $max_index =
max
map { $#{ $_ } }
values %hash;
# transpose hash-of-arrays and print CSV to STDOUT
my $csv = Text::CSV->new();
$csv->eol("\n");
$csv->print(\*STDOUT, \@column_order);
for my $index (0..$max_index) {
my @row =
map { $hash{$_}->[$index] // '' }
@column_order;
$csv->print(\*STDOUT, \@row);
}
exit 0;
__DATA__
column1 1 2 3
column2 4 5 6 7
column3 8 9
column4 10 11 12
column5 13 14 15 16 17 18
column6
column7 19 20 21 22
column8 23
column9 24 25 26
column10 27 28 29 30
使用嵌入式测试数据运行
$ perl dummy.pl
column1,column2,column3,column4,column5,column6,column7,column8,column9,column10
1,4,8,10,13,,19,23,24,27
2,5,9,11,14,,20,,25,28
3,6,,12,15,,21,,26,29
,7,,,16,,22,,,30
,,,,17,,,,,
,,,,18,,,,,