2016-08-17 5 views
-3

私は以下のような構造を持っています。Perl:複雑なハッシュから表形式に出力するフォーマット

my %hash = (
      'P' => { 
        '4' => [ 
          '1/4/1 2', 
          '1/4/1 3' 
          ], 
        '2' => [ 
          '1/2/1 1', 
          '1/2/5 4' 
          ] 
       }, 
      'Q' => { 
        '4' => [ 
          '1/4/1 3'  
          ], 
        '3' => [ 
          '1/3/1 1' 
          ], 
        '5' => [ 
          '1/5/1 1' 
          ] 
        }, 
     ); 

私はそれを好きなようにフォーマットします。

Node      2   3   4    5 

P      1/2/1 1     1/4/1 2   
P      1/2/5 4     1/4/1 3 
Q         1/3/1 1  1/4/1 3  1/5/1 1 

私は現在それを試みています。最後に、私はそれを優れたものにする必要があります。私はこれのようなものはいくつかの微調整で動作するかもしれないと思います。

my %seen; 
my @headers = sort { $a <=> $b } grep {!$seen{$_}++} map{ keys %{$hash{$_}} }keys %hash; 
print "node", ' ' x 30, join(" " x 10, @headers),"\n"; 

foreach my $node (keys %hash) { 
    my @values; 
    foreach my $num (keys %{$hash{$node}}) { 
     foreach my $klm (@{$hash{$node}{$num}}) { 
      push (@values,$klm); 
     } 
    } 
    foreach my $i (0 .. $#values) { 
     print "$node $values[$i]\n"; 
    } 
} 

さらなる提案があります。

+0

出力は画面用ですが、CSVリーダー用ではありませんか? – simbabque

+0

@simbabque最後に、私はそれをExcelに入れる必要があります。 –

+0

サンプル出力は完了していますか? – simbabque

答えて

2

をテストされています私は行と列を使って作業し、個々のフィールドをターゲットにする方が、出力を直接混乱させるよりも簡単だと思います。

use strict; 
use warnings 'all'; 
use Excel::Writer::XLSX; 

my %hash = (
    'P' => { 
     '4' => [ '1/4/1 2', '1/4/1 3' ], 
     '2' => [ '1/2/1 1', '1/2/5 4' ] 
    }, 
    'Q' => { 
     '4' => ['1/4/1 3'], 
     '3' => ['1/3/1 1'], 
     '5' => ['1/5/1 1'] 
    }, 
); 
my %seen; 
my @headers = sort { $a <=> $b } 
    grep { !$seen{$_}++ } 
    map { keys %{ $hash{$_} } } 
    keys %hash; 

# count how many rows each node has 
my %number_of_rows; 
foreach my $node (keys %hash) { 
COUNT_ROWS: foreach my $header (keys %{ $hash{$node} }) { 
     $number_of_rows{$node} = scalar @{ $hash{$node}->{$header} }; 
     last COUNT_ROWS; 
    } 
} 

my $workbook = Excel::Writer::XLSX->new('test.xlsx'); 
my $worksheet = $workbook->add_worksheet; 

# write the headers and save the cols 
my %col_headings; 
$worksheet->write(0, 0, 'Node'); 
for (my $i = 0; $i <= $#headers; $i++) { 
    $col_headings{ $headers[$i] } = $i + 1; 
    $worksheet->write(0, $i + 1, $headers[$i]); 
} 

my $row  = 1; # overall row in the Excel file 
my $node_row = 0; # current row for the current node 
NODE: foreach my $node (sort keys %hash) { 

    # write the node value (letter P, Q) 
    $worksheet->write($row, 0, $node); 

    # iterate the columns ... 
    foreach my $header (@headers) { 
     # ... but only write one that has a value 
     $worksheet->write( 
      $row, 
      $col_headings{$header}, 
      $hash{$node}->{$header}->[$node_row] 
     ) if exists $hash{$node}->{$header}; 
    } 

    $row++; # always go to a new row 

    if (++$node_row < $number_of_rows{$node}) { 
     # but if we have not done all the rows for the current node, 
     # redo this node in a new row with the next node_row 
     redo NODE; 
    } 
    else { 
     # or reset the node_row 
     $node_row = 0; 
    } 
} 

これは、コードを使用してすべてのヘッダーを検索します。どのヘッダーにどの列があるかを割り当て、ノードごとに行を数えます。次に、redoを使用してノードを繰り返し、そのノードのすべての行がなくなるまで1つのノードを継続します。これは、現在のノード行のカウンタをインクリメントしておくことで行います。同時に、全体の行カウンタを常にインクリメントしてテーブルの下に移動します。

これは次のようなものです。

screenshot of open office

コードは少し厄介ですが、それは仕事を取得します。とにかく、これは一度しか忘れないような仕事のようです。

0

なぜあなたの試みはしないでください:コメント

ため

my %seen; 
my @headers = sort { $a <=> $b } grep {!$seen{$_}++} map{ keys %{$hash{$_}} }keys %hash; 

printf("%-25s", "node"); 

foreach my $node (@headers) 
{ 
    printf("%-25s", $node); 
} 
print "\n"; 


foreach my $node (keys %hash) { 

    printf "%-25s", $node; 
    foreach my $num (@headers) 
    { 
    if(defined($hash{$node}{$num})) 
    { 
     my $string = join(" ", @{$hash{$node}{$num}});  
     printf "%-25s", $string ; 
    } 
    else 
    { 
      printf "%-25s", " " ; 
    }  
    } 
    print "\n"; 
} 

@simbabqueおかげでこのバージョンでは、デバッグと私は、Excelファイルを直接ので、それをやった

+0

私はこれがどのように使われているのか分かりません。 [編集]し、実用的な例を含めてください。 – simbabque

+1

右中括弧が欠落しています。追加すると、 'Q ARRAY(0x1cc0b20)\ nARRAY(0x1cc09a0)'の形式でhashrefを出力します。 – simbabque

関連する問題