Конвертировать хэш в CSV-файл - PullRequest
1 голос
/ 24 декабря 2010

Я получил хеш:

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

Нужна помощь в выяснении этого кода.

Ответы [ 5 ]

4 голосов
/ 24 декабря 2010

Первый шаг:

  • 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.

2 голосов
/ 24 декабря 2010

Решение с помощью 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;
1 голос
/ 24 декабря 2010

Выезд Текст :: CSV :: Slurp .Это позволит вам превратить хэш в CSV и наоборот.

1 голос
/ 24 декабря 2010

Если вы перебираете хеш и создаете строку для каждого ключа, каждый из них будет повторяться три раза; вместо этого создайте еще один хеш со всеми make, перебрав% hash, распаковав make и установив $ make {$ make} = 1. Затем выполните цикл по нему, чтобы получить строки.

Когда вы извлекаете make из ключа хэша%, используйте /\./ в качестве шаблона разделения; split всегда использует шаблон, а не простую строку (с одним нечетным исключением), и вы не хотите разбивать каждый символ, что и есть split. будет делать (спасибо, codaddict, за указание на эту часть).

'$make.Blue' использует одинарные кавычки, поэтому не будет интерполировать переменную. Вместо этого используйте "$make.Blue".

Перемещение открытия и закрытия до и после цикла @lines соответственно. Нет причин открывать файл для каждой строки.

Не забывайте "\ n" в конце каждой строки (если только вы не используете флаг -l или говорите вместо print).

0 голосов
/ 24 декабря 2010

Для тех, кому интересно, я смог разобраться, спасибо всем за помощь!

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); 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...