Longest match wins - how to do it Perl way?

A

A. Farber

Hi, I have a simple problem, which I have solved, but
my solution feels ugly to me. Any improvements please?

A web form contains a list of project names. And for
some projects there are mailing lists, which I need
to display if the matching project has been selected.

Some project names begin with the same string, like
"p1881_aq_" and "p1881". In those cases only the longest
match should be taken. Here is how I tried to solve it:

# put the longest keys first, to make them win

my @KEYS = qw( p1881_aq_ p1881_ p1972_ p1981_ p2311_ );

my %MAIL = (p1881_aq_ => {name => 'Project Aqua',
mail => '(e-mail address removed)'},
p1881_ => {name => 'Project Alpha',
mail => '(e-mail address removed)'},
p1972_ => {name => 'Project Beta',
mail => '(e-mail address removed)'},
p1981_ => {name => 'Project Gamma',
mail => '(e-mail address removed)'},
p2311_ => {name => 'Project Theta',
mail => '(e-mail address removed)'},
);

......
for my $p (@selected_projects) {
for my $k (@KEYS) {
if (0 == index $p, $k) {
printf q{<A HREF="MAILTO:%s">%s</A>},
$MAIL{$k}->{mail}, $MAIL{$k}->{name};
last;
}
}
}
 
B

Bob Walton

A. Farber said:
Hi, I have a simple problem, which I have solved, but
my solution feels ugly to me. Any improvements please?

A web form contains a list of project names. And for
some projects there are mailing lists, which I need
to display if the matching project has been selected.

Some project names begin with the same string, like
"p1881_aq_" and "p1881". In those cases only the longest
match should be taken. Here is how I tried to solve it:

# put the longest keys first, to make them win

my @KEYS = qw( p1881_aq_ p1881_ p1972_ p1981_ p2311_ );

my %MAIL = (p1881_aq_ => {name => 'Project Aqua',
mail => '(e-mail address removed)'},
p1881_ => {name => 'Project Alpha',
mail => '(e-mail address removed)'},
p1972_ => {name => 'Project Beta',
mail => '(e-mail address removed)'},
p1981_ => {name => 'Project Gamma',
mail => '(e-mail address removed)'},
p2311_ => {name => 'Project Theta',
mail => '(e-mail address removed)'},
);

.....
for my $p (@selected_projects) {
for my $k (@KEYS) {
if (0 == index $p, $k) {
printf q{<A HREF="MAILTO:%s">%s</A>},
$MAIL{$k}->{mail}, $MAIL{$k}->{name};
last;
}
}
}

Your solution looks pretty good to me. A couple of debatable things
that might make it more "Perlish": One could make the search for keys
into a regexp, and one could interpolate the variables into the print
string rather than using printf:

$KEYS=qr/^(p1881_aq_|p1881_|p1972_|p1981_|p2311_);
...
for my $p (@selected_projects){
if($p=~$KEYS){
print "<A HREF=\"MAILTO:$MAIL{$1}->{mail}\">$MAIL{$1}->{name}</A>";
}
}
 
J

John Bokma

Bob said:
print "<A HREF=\"MAILTO:$MAIL{$1}->{mail}\">$MAIL{$1}->{name}</A>";

using qq() you don't need to escape the " inside, or you can use single
quotes for the href value.
 
B

Big and Blue

A. Farber said:
# put the longest keys first, to make them win

my @KEYS = qw( p1881_aq_ p1881_ p1972_ p1981_ p2311_ );

my %MAIL = (p1881_aq_ => {name => 'Project Aqua',

A bit of a maintenance problem? Why not let Perl generate @KEYS?

my @KEYS = sort { length($b) said:
for my $p (@selected_projects) {
for my $k (@KEYS) {

last if (length($k) < length(p)); # Useful if you have a lot
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,769
Messages
2,569,581
Members
45,055
Latest member
SlimSparkKetoACVReview

Latest Threads

Top