in reply to Re: ugly code
in thread ugly code

Better:
$string =~ s/(a|b)/$map{ $1 }/g;

You may be able to construct the pattern out of the hash keys:

$pattern = join '|', map quotemeta, keys %map; $string =~ s/($pattern)/$map{ $1 }/go; # /o only if the pattern never + changes
For not too recent perls, you get a better performance if you build the pattern out of the keys with a module like Regexp::Assemble or Regex::PreSuf;
use Regex::PreSuf; my $pattern= presuf(keys %map); $string =~ s/($pattern)/$map{ $1 }/go;

Allegedly, the most modern perl will optimize it for you, and possibly even with better (faster) results.

update (July 9) ysth sent me a msg with a caution for the case where one of the hash keys is a prefix of another key, for example: ('foo', 'food'). In that case, to make sure the longest key is matched, you should sort the keys when constructing the pattern so the longest key comes first. ysth proposed:

$pattern = join '|', map quotemeta, sort { length($b) <=> length($a) } + keys %map;
which will work, but so will this:
$pattern = join '|', map quotemeta, sort { $b cmp $a } keys %map;
because with two strings where one is a prefix of another, the longer one will compare as "greater" than the shorter one.

You need not worry when using Regex::PreSuf because it'll always attempt to match the longest string, first.

Replies are listed 'Best First'.
Re^3: ugly code
by johngg (Canon) on Jul 08, 2007 at 22:15 UTC
    I don't know whether this is better or not but I tend to use the quotishness of compiled regexen with a localized list separator rather than join.

    my $rxPattern; { local $" = q{|}; $rxPattern = qr{(?x) (@{ [ map { quotemeta } keys %map ] }) }; } $string =~ s{$rxPattern}{$map{$1}}g;

    I'd be interested to know if this is a sensible approach.

    Cheers,

    JohnGG