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

I want the 3 $_ instruction to disappear and the single instruction, that emerges, to work on the array at once without while, ugly braces etc.

foreach ( @subtitle ) { $_ =~ s/º/s/; $_ =~ s/þ/t/; $_ =~ s/ª/S/; }
I would like it to be something like:
@subtitle =~ s/list/list/g;
Thanks for all your time, I really appreciate it.

20070708 Janitored by Corion: Moved text out of code tags, as per Writeup Formatting Tips

Replies are listed 'Best First'.
Re: ugly code
by Limbic~Region (Chancellor) on Jul 07, 2007 at 22:29 UTC
    fubber,
    Ultimately you are going to have to loop even if you don't want to. That said, it seems that you have a list of characters that are being translated to other characters. Perhaps you want tr instead.
    tr/abc/efg/ for @subtitles;

    Cheers - L~R

Re: ugly code
by almut (Canon) on Jul 07, 2007 at 22:29 UTC

    If it's single chars being replaced by single chars, you might also use tr///

    map tr/ºþª/stS/, @subtitle;
Re: ugly code
by Joost (Canon) on Jul 07, 2007 at 22:24 UTC
Re: ugly code
by jZed (Prior) on Jul 07, 2007 at 22:23 UTC
    @subtitles = map { s/º/s/; s/þ/t/; s/ª/S/; $_; } @subtitles;
Re: ugly code
by parv (Parson) on Jul 08, 2007 at 03:24 UTC

    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.

      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