这是我的代码:
my %hash = (
'2564' => {
'st_responsible' => 'mname1',
'critical' => '',
'last_modified_by' => 'teamname1',
'transstatus' => '',
'rt_res' => 'pname1'
},
'2487' => {
'st_responsible' => 'mname2',
'critical' => '',
'last_modified_by' => 'teamname2',
'transstatus' => '',
'rt_res' => ''
}
);
print "xnum,st_responsible,critical,last_modified_by,transstatus,rt_res\n";
foreach my $x_number (sort keys %hash)
{
print "$x_number";
foreach my $element (keys %{$hash{$x_number}})
{
print ",$hash{$x_number}{$element}";
}
print "\n";
}
预期输出
xnum,st_responsible,critical,last_modified_by,transstatus,rt_res
2487,mname2,,teamname2,,
2564,mname1,,teamname1,,pname1
实际输出
xnum,st_responsible,critical,last_modified_by,transstatus,rt_res
2487,mname2,,,teamname2,
2564,mname1,,,teamname1,pname1
请帮助我告诉我如何保留此数据结构的顺序,然后将其写入CSV
文件。
答案 0 :(得分:1)
Perl不保证哈希中项目的顺序,这是问题的根本原因。即使两个具有相同键的不同哈希也可以具有不同的键顺序。它可能也因平台和架构以及perl版本而异。
您需要使用要按正确顺序打印的键列表定义另一个数组。
my @keys = qw(st_responsible critical last_modified_by transstatus rt_res);
foreach my $element (@keys) {
... print the value
}
编辑:当您尝试编写CSV文件时,请考虑使用Text::CSV来处理特殊字符,更正格式以及类似的内容。
答案 1 :(得分:1)
我建议为此,你最好用slice
来做这件事,这是一种从特定顺序的哈希中提取值列表的方法吗?
#configure field order
my @order = qw ( st_responsible critical last_modified_by transstatus rt_res );
#print header row
print join (",", "xnum", @order ),"\n";
#iterate the rows
foreach my $key ( sort keys %hash ) {
#extract hash slice and join it with commas
print join ( ",", $key, @{$hash{$key}}{@order} ),"\n";
}
这给出了:
xnum,st_responsible,critical,last_modified_by,transstatus,rt_res
2487,mname2,,teamname2,,
2564,mname1,,teamname1,,pname1
您可以考虑使用Text::CSV
- 但我建议在这种情况下它过度使用,最好在有引号和引用字段分隔符时使用。 (而你没有)。
如果您不仅要处理空键,还要处理缺失的键,则可以使用map
:
my @order = qw ( st_responsible critical last_modified_by
transstatus missing rt_res extra_field_here );
print join (",", "xnum", @order ),"\n";
foreach my $key ( sort keys %hash ) {
print join ( ",", $key, map { $_ // '' } @{$hash{$key}}{@order} ),"\n";
}
(否则你会得到一个关于undef值的警告)。
答案 2 :(得分:0)
可能有一种更为明智的方法可以实现这一目标,但请试一试:
use warnings;
use strict;
open my $csv_out, '>', 'out.csv' or die $!;
my @keys = qw(2487 2564);
my @vals = qw(st_responsible critical last_modified_by transstatus rt_res);
print $csv_out "xnum,st_responsible,critical,last_modified_by,transstatus,rt_res\n";
for my $key (@keys){
print $csv_out "$key,";
for my $vals (@vals){
$vals eq $vals[-1] ? print $csv_out "$hash{$key}{$vals}\n" : print $csv_out "$hash{$key}{$vals},";
}
}
这将以逗号分隔的值打印到csv文件out.csv
,保持原始顺序(通过迭代数组)。如果它是最后一个值,它将打印换行符。
--- OUTPUT ---
xnum,st_responsible,critical,last_modified_by,transstatus,rt_res
2487,mname2,,teamname2,,
2564,mname1,,teamname1,,pname1