in reply to ugly code

Yet another way to do it is to use a hash (which in OP's case seem out of proportion) ...

my $string = 'bulky axe'; my %map = ( 'a' => 2 , 'b' => 4 ); $string =~ s/$_/$map{ $_ }/g for keys %map;

And, Python may have a solution for your "white, ugly braces" problem.

Replies are listed 'Best First'.
Re^2: ugly code
by bart (Canon) on Jul 08, 2007 at 16:10 UTC
    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.

      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