0

これは私がPerlのTemplateToolkitを使用して書いているものですが、より一般的なアルゴリズムの問​​題です。私の基本的な問題は、次のようなデータ構造が与えられていることです。

my @array = (
    [qw /00 01/],
    [qw /10/],
    [qw /20 21/],
    [qw /30 31 32 33 /],
);

このような出力が必要です(説明のために簡略化):

<00>
  <10>
    <20> <30>(00/10/20/30)</30> <31>(00/10/20/31)</31>
         <32>(00/10/20/32)</32> <33>(00/10/20/30)</33>
    </20>
    <21> <30>(00/10/21/30)</30> <31>(00/10/21/31)</31>
         <32>(00/10/21/31)</32> <33>(00/10/21/31)</33>
    </21>
  </10>
</00>
<01>
  <10>
    <20> <30>(01/10/20/30)</30> <31>(01/10/20/31)</31>
         <32>(01/10/20/32)</32> <33>(01/10/20/33)</33>
    </20>
    <21> <30>(01/10/21/30)</30> <31>(01/10/21/31)</31>
         <32>(01/10/21/32)</32> <33>(01/10/21/33)</33>
    </21>
</10>
</01>

これは、実際の出力であるネストされたhtmlテーブルの簡略化された例です。中央ノードのパスは、実際には、ネストされたテーブルにデータを入力するために別のサブルーチンに呼び出される引数です。元の配列構造の転置が役立つと確信しているので、Array :: Transpose :: Raggedを作成し、本日早くにCPANでリリースしました。

ネストされた構造を内側から外側に構築する実装を管理しましたが(perlのテンプレートツールキットを使用-以下を参照)、構造の外側に到達するまでに、必要なデータを入力する機会がなくなりました。中央ノード。価値のあるものの実装は次のとおりです。

[% SET inner = "(path data should go here)" %]
[% MACRO process_groups(line, inner) BLOCK %]
[% FOREACH l IN line %]
<[% l %]>[% inner %]</[% l %]>
[% END %]
[% END %]
[% WHILE (x = records.pop) %]
[% inner = process_groups(x, inner) %]
[% END %]
[% inner %]

これを正しくするために私が取るべきアプローチの提案

アップデート:

興味のために、私は受け入れられた答えのTTバージョンを載せると思いました。TTはperlほど柔軟ではないため、少し注意が必要ですが、次のようになります。

#!/usr/bin/env perl
use warnings;
use strict;
use Template;
my $template = Template->new();
my @array = (
    [ qw/00 01/ ], [ qw/10/ ],[ qw/20 21/ ], [ qw/30 31 32 33/ ]);
my $stash = { records => \@array, };
$template->process(\*DATA, $stash) || die $template->error(), "\n";

__END__
[% MACRO print_output(data, path_elements) BLOCK; %]
[% current = data.0; remaining = data.slice(1); %]
[% FOREACH d IN current %]
<[% d %]>
[% IF remaining.size > 0  %]
[% path_elements.push(d); print_output(remaining, path_elements); %]
[% SET discard = path_elements.pop %]
[% ELSE %]
([% path_elements.join('/')  _ '/' _ d  %])
[% END %]
</[% d %]>
[% END %]
[% END %]
[% SET path = []; print_output(records, path) %]

さらに、TTの実際のネストされたテーブル構造は次のとおりです。

[% MACRO print_output(data, path_elements) BLOCK; %]
<table> <tr>
[% current = data.0; remaining = data.slice(1); %]
[% FOREACH d IN current %]
<th>[% d %]</th>
[% END %] </tr>
<tr>
[% FOREACH d IN current %]
[% IF remaining.size > 0  %]
<td id="[% d %]">[% path_elements.push(d); print_output(remaining, path_elements); %]</td>
[% SET discard = path_elements.pop %]
[% ELSE %]
<td>([% path_elements.join('/')  _ '/' _ d  %])</td>
[% END %]
[% END %]
</tr></table>
[% END %]
[% SET path = []; print_output(records, path) %]
4

2 に答える 2

1

テンプレートツールキットソリューションが必要な場合は、以下を参照してください。

Perlコード:

use strict;
use Template;

my @array = (
    [qw /00 01/],
    [qw /10/],
    [qw /20 21/],
    [qw /30 31 32 33/],
);

my $tt = Template->new(POST_CHOMP => 1);

$tt->process('template.tt', { DATA => \@array }) or die "TT Error : " . $tt->error();

TTテンプレート(修正済み)(template.tt):

[% BLOCK display -%]
   [% arr = DATA.$i %]
   [% IF i == DATA.max %]
      [% FOREACH t IN arr -%]
         <[% t %]>
             [% tmp_c = c.substr(1) %]
             [% "($tmp_c/$t)" %]
         </[% t %]>
      [% END %]
   [% ELSE %]
      [% FOREACH t IN arr -%]
         <[% t %]>
            [% INCLUDE display i = i+1, c = "$c/$t" %]
         </[% t %]>
      [% END -%]
   [% END %]
[% END -%]

[% INCLUDE display i = 0, c = '' %]
于 2010-11-04T21:31:23.473 に答える
1

あなたが取り組んでいる状況を完全に理解しているのかわかりませんが、一般的な問題を突き止めます。

use strict;
use warnings;

my @array = (
    [ qw/00 01/ ],
    [ qw/10/ ],
    [ qw/20 21/ ],
    [ qw/30 31 32 33/ ],
);
print_output(\@array);

sub print_output {
    my ($data, @path_elements) = @_;
    my $level = @path_elements;
    my ($current, @remaining) = @$data;
    for my $d (@$current){
        print '  ' x $level, "<$d>\n";    
        if (@remaining){
            print_output(\@remaining, @path_elements, $d);        
        }
        else {
            print '  ' x ($level + 1), "(", join('/', @path_elements, $d), ")\n";
        }
        print '  ' x $level, "</$d>\n";
    }
}
于 2010-11-04T13:52:19.583 に答える