Note that there are some explanatory texts on larger screens.

plurals
  1. POConstructing "introspective" nested html tables
    text
    copied!<p>This is something I'm writing using the Template Toolkit in Perl, but it's more a generic algorithm problem. My basic problem is that given a data structure like this:</p> <pre><code>my @array = ( [qw /00 01/], [qw /10/], [qw /20 21/], [qw /30 31 32 33 /], ); </code></pre> <p>I need output like this (simplified for illustration):</p> <pre><code>&lt;00&gt; &lt;10&gt; &lt;20&gt; &lt;30&gt;(00/10/20/30)&lt;/30&gt; &lt;31&gt;(00/10/20/31)&lt;/31&gt; &lt;32&gt;(00/10/20/32)&lt;/32&gt; &lt;33&gt;(00/10/20/30)&lt;/33&gt; &lt;/20&gt; &lt;21&gt; &lt;30&gt;(00/10/21/30)&lt;/30&gt; &lt;31&gt;(00/10/21/31)&lt;/31&gt; &lt;32&gt;(00/10/21/31)&lt;/32&gt; &lt;33&gt;(00/10/21/31)&lt;/33&gt; &lt;/21&gt; &lt;/10&gt; &lt;/00&gt; &lt;01&gt; &lt;10&gt; &lt;20&gt; &lt;30&gt;(01/10/20/30)&lt;/30&gt; &lt;31&gt;(01/10/20/31)&lt;/31&gt; &lt;32&gt;(01/10/20/32)&lt;/32&gt; &lt;33&gt;(01/10/20/33)&lt;/33&gt; &lt;/20&gt; &lt;21&gt; &lt;30&gt;(01/10/21/30)&lt;/30&gt; &lt;31&gt;(01/10/21/31)&lt;/31&gt; &lt;32&gt;(01/10/21/32)&lt;/32&gt; &lt;33&gt;(01/10/21/33)&lt;/33&gt; &lt;/21&gt; &lt;/10&gt; &lt;/01&gt; </code></pre> <p>This being a simplified example of the nested html tables that are the real output. The path at the central nodes are actually the arguments to be called to another subroutine to populate the nested tables with data. I'm fairly certain that a transpose of the original array structure will be useful, so I wrote <a href="http://search.cpan.org/perldoc?Array%3a%3aTranspose%3a%3aRagged" rel="nofollow">Array::Transpose::Ragged</a> and released it on CPAN earlier today.</p> <p>I managed an implementation which builds the nested structure from the inside to the outside (using perl's <a href="http://search.cpan.org/perldoc?Template" rel="nofollow">Template Toolkit</a> - see below), but by the time I get to the outer parts of the structure I no longer have the opportunity to populate the required data at the central nodes. Here's that implementation for what it's worth:</p> <pre><code>[% SET inner = "(path data should go here)" %] [% MACRO process_groups(line, inner) BLOCK %] [% FOREACH l IN line %] &lt;[% l %]&gt;[% inner %]&lt;/[% l %]&gt; [% END %] [% END %] [% WHILE (x = records.pop) %] [% inner = process_groups(x, inner) %] [% END %] [% inner %] </code></pre> <p>Any suggestions for the approach I should be taking to get this right</p> <p>UPDATE:</p> <p>For interest, I thought I'd put the TT version of the accepted answer up. A little tricky because TT isnt quite as flexible as perl, but here goes:</p> <pre><code>#!/usr/bin/env perl use warnings; use strict; use Template; my $template = Template-&gt;new(); my @array = ( [ qw/00 01/ ], [ qw/10/ ],[ qw/20 21/ ], [ qw/30 31 32 33/ ]); my $stash = { records =&gt; \@array, }; $template-&gt;process(\*DATA, $stash) || die $template-&gt;error(), "\n"; __END__ [% MACRO print_output(data, path_elements) BLOCK; %] [% current = data.0; remaining = data.slice(1); %] [% FOREACH d IN current %] &lt;[% d %]&gt; [% IF remaining.size &gt; 0 %] [% path_elements.push(d); print_output(remaining, path_elements); %] [% SET discard = path_elements.pop %] [% ELSE %] ([% path_elements.join('/') _ '/' _ d %]) [% END %] &lt;/[% d %]&gt; [% END %] [% END %] [% SET path = []; print_output(records, path) %] </code></pre> <p>And even better here's the actual nested table structure in TT:</p> <pre><code>[% MACRO print_output(data, path_elements) BLOCK; %] &lt;table&gt; &lt;tr&gt; [% current = data.0; remaining = data.slice(1); %] [% FOREACH d IN current %] &lt;th&gt;[% d %]&lt;/th&gt; [% END %] &lt;/tr&gt; &lt;tr&gt; [% FOREACH d IN current %] [% IF remaining.size &gt; 0 %] &lt;td id="[% d %]"&gt;[% path_elements.push(d); print_output(remaining, path_elements); %]&lt;/td&gt; [% SET discard = path_elements.pop %] [% ELSE %] &lt;td&gt;([% path_elements.join('/') _ '/' _ d %])&lt;/td&gt; [% END %] [% END %] &lt;/tr&gt;&lt;/table&gt; [% END %] [% SET path = []; print_output(records, path) %] </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload