我得到了哈希:
%hash = (
Honda.Blue => '10',
Honda.Red => '10',
Honda.Yellow => '60',
Ford.Blue => '20',
Ford.Red => '25',
Ford.Yellow => '26',
Toyota.Blue => '17',
Toyota.Red => '16',
Toyota.Yellow => '18',
);
需要将此哈希转换为带有以下标题的csv文件(make,blue_volume,red_volume,yellow_volume)并将其填入数据
#Make,blue_volume,red_volume,yellow_volume
#Honda,10,10,60
#Ford,20,25,26
#Toyota,17,16,18
loop over %hash
@array = split('.',$key);
$make=$array[0];
$line = "$make,$hash{'$make.Blue'},$hash{'$make.Red'},$hash{'$make.Yellow'}";
push(@lines,$line);
foreach (@lines)
{
open (LOG, '>>summary.csv');
print LOG "$_";
close (LOG);
}
需要帮助搞清楚这段代码。
答案 0 :(得分:4)
第一步:
use strict;
说:
Bareword "Honda" not allowed while "strict subs" in use at xx.pl line 4.
这不是批准的创建哈希的方法。我建议:
use strict;
use warnings;
my %hash = (
Honda => { Blue => '10', Red => '10', Yellow => '60' },
Ford => { Blue => '20', Red => '25', Yellow => '26' },
Toyota => { Blue => '17', Red => '16', Yellow => '18' },
);
然后,您应该使用Text::CSV。但是,通过简单的操作输出并不是那么难。我们可以利用你要求蓝色,红色,黄色碰巧按字母顺序排列的事实:
print "make,blue_volume, red_volume,yellow_volume\n";
foreach my $make (sort keys %hash)
{
print "$make";
foreach my $colour (sort keys %{$hash{$make}})
{
print ",$hash{$make}{$colour}";
}
print "\n";
}
对于示例哈希,输出为:
make,blue_volume, red_volume,yellow_volume
Ford,20,25,26
Honda,10,10,60
Toyota,17,16,18
如果有任何需要使用引号或其他内容的风险,我会使用Text :: CSV。
答案 1 :(得分:2)
使用List :: MoreUtils的解决方案。
#!/usr/bin/env perl
use warnings;
use 5.012;
use List::MoreUtils qw/first_index/;
use Text::CSV;
my $file_out = 'my_new_file.csv';
my %hash = (
'Honda.Blue' => '10',
'Honda.Red' => '10',
'Honda.Yellow' => '60',
'Ford.Blue' => '20',
'Ford.Red' => '25',
'Ford.Yellow' => '26',
'Toyota.Blue' => '17',
'Toyota.Red' => '16',
'Toyota.Yellow' => '18',
);
my @brands = qw( Honda Ford Toyota );
my @colors = qw( Blue Red Yellow );
my @array;
for my $key ( keys %hash ) {
my( $brand, $color ) = split /\./, $key, 2;
my $idx_1 = first_index { $_ eq $brand } @brands;
my $idx_2 = first_index { $_ eq $color } @colors;
$array[$idx_1][0] = $brand;
$array[$idx_1][$idx_2+1] = $hash{$key};
}
my $csv = Text::CSV->new ( { binary => 1, eol => $/, auto_diag => 2 } )
or die Text::CSV->error_diag();
my $col_names = [ qw( Make blue_volume red_volume yellow_volume ) ];
open my $fh, '>:encoding(UTF-8)', $file_out or die $!;
$csv->print ( $fh, $col_names );
$csv->print ( $fh, $_ ) for @array;
close $fh;
答案 2 :(得分:1)
如果迭代哈希并为每个键创建一行,则每个键重复三次;相反,通过循环%hash,提取make,并设置$ makes {$ make} = 1,创建另一个包含所有品牌的哈希。然后循环遍历它以生成你的行。
从%hash键中提取make时,使用/\./
作为拆分模式; split总是使用一个模式,而不是一个简单的字符串(有一个奇怪的例外),你不想在每个字符上拆分,这就是拆分'。'会这样做(谢谢,抄送,指出这部分)。
'$make.Blue'
使用单引号,因此不会插入变量。请改用"$make.Blue"
。
分别在@lines循环之前和之后移动打开和关闭。没有理由为每一行打开文件。
不要忘记每行末尾的“\ n”(除非你使用-l标志或者说而不是打印)。
答案 3 :(得分:1)
结帐Text::CSV::Slurp。它允许您将哈希转换为CSV,反之亦然。
答案 4 :(得分:0)
对于那些感兴趣的人,我能够弄清楚,感谢大家的帮助!
my %hash;
$hash{'aaa.biz'} = 'domainRegistered';
$hash{'aaa.com'} = 'domainRegistered';
$hash{'aaa.info'} = 'domainRegistered';
$hash{'aaa.net'} = 'domainRegistered';
$hash{'aaa.org'} = 'domainRegistered';
$hash{'bbb.biz'} = 'domainRegistered';
$hash{'bbb.com'} = 'domainRegistered';
$hash{'bbb.info'} = 'domainRegistered';
$hash{'bbb.org'} = 'domainRegistered';
$hash{'bbb.us'} = 'domainRegistered';
foreach $key (sort keys %hash)
{
@array=split("\\.",$key);
push (@names, $array[0]);
}
#Extract unique values and sort
my %seen = ();
my @result = grep { !$seen{$_}++ } @names;
@names = sort { $a <=> $b } @result;
foreach $element (@names)
{
foreach $key (sort keys %hash)
{
@array=split("\\.",$key);
if (@array [0] eq $element){push (@values, $hash{$key});}
}
$values = join(",",@values);
$line = "$element,$values";
undef @values;
push(@lines,$line);
}
print join("\n",@lines);
open (summary, '>>summary.csv');
print summary join("\n",@lines);
close (summary);