In seach of a more elegant foreach
kiat
created: 2004-06-15 21:29:35
Hi monks,

I'm wondering if there's a more elegant way of achieving what I'm doing with the code below (somewhat related to my node [366914]):

my $matrix_ref = [[1, a1, z1],[1, a1, z2], [1, a1, z3], [2, a2, z1], [2, a2, z2], [3, a3, z1]];

my ($html_str, $key, $count);

# id, a_item, z_item
foreach my $row (@$matrix_ref) {
  if ($row->[0] eq $key) {
    $html_str .= qq~$row->[2]\n~;
  }
  else {
    $html_str .= '' if $count > 0;
    $html_str .= qq~\n~;
  }
  $key = $row->[0];
  $count++;
}

# output
1 a1 z1 z2 z3
2 a2 z1 z2
3 a3 z1

Lots of thanks in advance :)






Re: In seach of a more elegant foreach
created: 2004-06-15 21:54:52

You have a natural refactoring, lets call it cell_wrap,

sub cell_wrap {
    join '', map {"
"} @_; } Since you're just choosing between values in your conditional, the trinary op ?: comes to mind. Finally, I'd keep the [foreach] loop pretty much as you have it, though I'll pare it down to [for] and name no temporaries.
for (@$matrix_ref) {
    $html_str .= cell_wrap(
        $_->[0] eq $key
        ? $_->[2]
        : (@{$_}[0..2]) );
    $key = $_->[0];
}

It would be a bigger improvement to separate logic from presentation by merging the records and then feeding $matrix_ref to a template engine like [cpan://Html::Template] or [cpan://Template|TT2].

Update: Arrgh! You changed your presentation code! Take this as another argument for templating.

After Compline,
Zaxo

Re^2: In seach of a more elegant foreach
created: 2004-06-15 22:11:16
Thanks, Zaxo!

Your code looks so much more elegant :)

Update: My apologies for changing the presenation code. I realised after I posted that I needed to put similar values in a table.

Re: In seach of a more elegant foreach
created: 2004-06-15 22:31:33
First off, there is a set of functions that will generate the HTML for you, in the [CGI] module. As it stands, your code doesn't emit well-formed HTML.

But, to use that set of functions, you need to change your data structure into something that is more easily handled. Warning - the variables are poorly named. But, it is tested.

my @x;
my $curr = '';
my @curr;
foreach my $ref (@$matrix_ref)
{
    my $k = $ref->[0] . $ref->[1];
    unless ($curr eq $k)
    {
        push @x, [ @curr ] if @curr;

        @curr = @$ref;
        $curr = $k;

        next;
    }

    push @curr, $ref->[2];
}
push @x, [ @curr ];

use CGI qw( :all );

$html_str = table( map { Tr( td( $_ ) ) } @x );

------
We are the carpenters and bricklayers of the Information Age.

Then there are Damian modules.... *sigh* ... that's not about being less-lazy -- that's about being on some really good drugs -- you know, there is no spoon. - [flyingmoose]

I shouldn't have to say this, but any code, unless otherwise stated, is untested

Re^2: In seach of a more elegant foreach
created: 2004-06-15 22:40:24
Ah, now I see how I can cleanly separate code from html. Thanks, dragonchild!
Re: In seach of a more elegant foreach
created: 2004-06-16 07:51:31

If you are handling matrices on a regular basis, I would use PDL. They have a bunch of modules for matrices and it might make your day a little easier.

Re: In seach of a more elegant foreach
created: 2004-06-16 10:52:21
I call shenanigans! You aren't using strict!

perlmonks.org content © perlmonks.org and cyocum, diotalevi, dragonchild, kiat, Zaxo

prlmnks.org © 2006 edmund von der burg (eccles & toad)

v 0.03

$row->[0]
$row->[1]
$row->[2]
$_