edimusrex has asked for the wisdom of the Perl Monks concerning the following question:

Hello fellow monks. What I am trying to accomplish is probably stupid simple but I am not sure how to go about it.
What I am trying to do is build an HTML email using a text block (which I do all the time) but include an array within the contents. I need to append each array element with "list" tags and in the past I would push the existing array elements to a new array with the list tags added so something like this

foreach(@existing_array) { push @new_array, "<li>$_</li>"; } my $html = <<EOF; <html> <body> <ul>@new_array</ul> </body> <html> EOF

Which works but I feel like it is an unnecessary step. Does any know a more efficient way of going about this? I hope it made sense.

Replies are listed 'Best First'.
Re: Joining an array within a text block
by toolic (Bishop) on May 18, 2015 at 16:07 UTC
    With your heredoc implementation, it makes sense to have a separate array. However, with simple for/push constructs like this, map is appropriate:
    my @new_array = map { "<li>$_</li>" } @existing_array;

    I haven't used them, but there are templating systems for creating HTML.

Re: Joining an array within a text block
by choroba (Cardinal) on May 18, 2015 at 16:10 UTC
    You can shorten foreach to for, or hide it in map:
    my $list = join "\n", map "<li>$_</li>", @existing_array;

    Or, you can use a templating system:

    #! /usr/bin/perl use warnings; use strict; use Template; my @array = ('Item 1', 'Item 2'); my $t = Template->new; my $list = << '__TT__'; <html> <body> <ul>[% FOR item IN list %] <li>[% item %]</li>[% END %] </ul> </body> <html> __TT__ $t->process(\$list, { list => \@array }, \*STDOUT);
    لսႽ† ᥲᥒ⚪⟊Ⴙᘓᖇ Ꮅᘓᖇ⎱ Ⴙᥲ𝇋ƙᘓᖇ
Re: Joining an array within a text block
by edimusrex (Monk) on May 18, 2015 at 16:54 UTC
    Thanks for you help again. Here is the solution I came up with

    sub mail { my ($changed,$updated) = @_; my $t = Template->new; my $to = 'xxx@xxx.com'; my $subject = "Webchanges Detected - $date"; my $body = <<EOF; <html> <body> <h2>Changes Detected :</h2> <hr width="80%" size="1"/> <br/> <b>Changed Values :</b> <ul>[% FOR changed IN list1 %] <li>[% changed %]</li>[% END %] </ul> <br/> <hr width="80%" size="1"/> <br/> <b>Updated Values :</b> <ul>[% FOR updated IN list2 %] <li>[% updated %]</li>[% END %] </ul> </body> </html> EOF $t->process(\$body, { list1 => \@{$changed}, list2 => \@{$updated} + }, \*STDOUT); my $msg = MIME::Lite->new( From => 'xxx@xxx.com', To => $to, Subject => $subject, Type => 'text/html', Data => $body, ) or die "Error creating multipart container: $!\n"; $msg->send or die "Failed To Send!: $!\n"; print "Message sent!\n"; }

    Well with out the template printing to standard out
Re: Joining an array within a text block
by Laurent_R (Canon) on May 18, 2015 at 16:57 UTC
    I would probably use map as suggested by toolic.

    But you could also use a syntax with a statement modifier:

    push @new_array, "<li>$_</li>" for @existing_array;
    Update: This post may seem somewhat useless after the preceding post from the Original Poster, but I had not seen that other post (posted only 3 minutes before) when I wrote mine. I wonder why two monks decided to downvote my post, which was just trying to offer another simplified and, I think, correct syntax, without making any comment. I am not complaining about that, I can perfectly accept that people don't like what I wrote, but I am just wondering why. I would be glad if they would let me know what they did not like in my post.
Re: Joining an array within a text block
by edimusrex (Monk) on May 18, 2015 at 16:12 UTC
    Excellent, I will look into both those options. Thanks again!