将哈希值转换为 csv 文件

发布于 2024-10-08 18:05:25 字数 760 浏览 3 评论 0原文

我得到一个散列:

%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',
);

需要将此散列转换为具有以下标头(make、blue_volume、red_volume、yellow_volume)的 csv 文件并用数据填充它

#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);
}

需要帮助弄清楚此代码。

I got a hash:

%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',
);

Need to convert this hash into a csv file with the following headers (make,blue_volume,red_volume,yellow_volume) and fill it with data

#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);
}

Need help figuring out this code.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

决绝 2024-10-15 18:05:25

第一步:

  • use strict; 说:
    • 在 xx.pl 第 4 行使用“strict subs”时不允许使用裸字“Honda”。

这不是创建哈希的经过批准的方式。我建议:

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

如果存在需要使用引号或其他任何内容的风险,我会使用文本::CSV。

First step:

  • use strict; says:
    • Bareword "Honda" not allowed while "strict subs" in use at xx.pl line 4.

That is not an approved way of creating the hash. I suggest:

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' },
);

Then, you should probably use Text::CSV. However, it is not all that hard to do output with simple manipulation. We can exploit the fact that you've asked for blue, red, yellow which happen to be in alphabetic order:

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";
}

For the sample hash, the output is:

make,blue_volume, red_volume,yellow_volume
Ford,20,25,26
Honda,10,10,60
Toyota,17,16,18

If there was any risk of needing to use quotes or anything else, I'd use Text::CSV.

爱你是孤单的心事 2024-10-15 18:05:25

使用 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;

A solution with 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;
爺獨霸怡葒院 2024-10-15 18:05:25

如果您迭代哈希并为每个键创建一行,则每个创建都会重复三次;相反,通过循环 %hash、提取 make 并设置 $makes{$make} = 1,创建另一个包含所有 make 的哈希。然后循环生成您的行。

当您从 %hash 键中提取 make 时,请使用 /\./ 作为分割模式; split 总是使用一种模式,而不是一个简单的字符串(有一个奇怪的例外),并且您不想对每个字符进行拆分,这就是 split '.' 的原因。会做(谢谢,codaddict,指出这部分)。

'$make.Blue' 使用单引号,因此不会插入变量。请改用 "$make.Blue"

将 open 和 close 分别移至 @lines 循环之前和之后。没有理由为每一行打开文件。

不要忘记每行末尾的“\n”(除非您使用 -l 标志或 say 而不是 print)。

If you iterate over the hash and make a line for each key, you will have each make repeated three times; instead, create another hash with all the makes by looping over %hash, extracting the make, and setting $makes{$make} = 1. Then loop over that to produce your lines.

When you extract the make from the %hash key, use /\./ as the split pattern; split always uses a pattern, not a simple string (with one odd exception), and you don't want to split on every character, which is what split '.' would do (thanks, codaddict, for pointing this part out).

'$make.Blue' uses single quotes, so it won't interpolate the variable. Use "$make.Blue" instead.

Move the open and close to before and after the @lines loop, respectively. There's no reason to open the file for each line.

Don't forget a "\n" at the end of each line (unless you are using the -l flag or say instead of print).

卸妝后依然美 2024-10-15 18:05:25

查看 Text::CSV::Slurp。它将允许您将哈希值转换为 CSV,反之亦然。

Check out Text::CSV::Slurp. It will allow you to turn a hash into CSV and vice versa as well.

执着的年纪 2024-10-15 18:05:25

对于那些有兴趣的人,我能够弄清楚,感谢大家的帮助!

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); 

For those interested I was able to figure it out, thanks for everyone's help!

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); 
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文