in reply to Difference between tr/// and s///?

The difference is that one translates single characters and one substitutes patterns. Which to use should depend mostly on what you are doing. If you are replacing pluses with spaces, then pick whichever you are more comfortable with or based on what direction the code is likely to evolve in.

If you foresee the code changing to s/[\s+]+/ /g one day, then starting with s/\+/ /g is probably a good idea. If you foresee the code changing to tr/+\-<>/ _()/, then starting with tr/+/ / is probably a good idea.

For these reasons, I usually prefer s/\+/ /g over tr/+/ /.

Some will make a big deal about tr/// usually being faster than s///. I make a big deal about the speed difference between tr/// and s/// usually being imperceptible. Benchmark has to do a lot of tricky things to make the difference measurable. tr/// is usually faster than s///, but not always and it almost always doesn't matter in the slightest.

Here is a benchmark to demonstrate both points:

#!/usr/bin/perl use Benchmark qw( cmpthese ); my( $count, $len )= @ARGV; $count ||= 10; $len ||= 5000; my $string= join '+', map { join '', map {('a'..'z')[rand(26)]} 0..rand($len) } 1..$count; sub subst { $string =~ s/\+/-/g; $string =~ s/\-/+/g; 0; } sub trans { $string =~ tr/\+/-/; $string =~ tr/\-/+/; 0; } cmpthese( -3, { a_s => \&subst, b_s => \&subst, a_t => \&trans, b_t => \&trans, } );
and the output:
Rate b_t a_t b_s a_s b_t 8190/s -- -1% -40% -40% a_t 8258/s 1% -- -39% -40% b_s 13615/s 66% 65% -- -1% a_s 13720/s 68% 66% 1% --

So here I've got an unusually long string (50,000 bytes) and the difference in speed between the two is about 0.00005 seconds. Most of the time your strings aren't that long so the difference is even less.

Sure, there are rare cases where you are doing hundreds of thousands of these operations on really long strings and these tiny difference add up. But even in such cases, if you manage to get them to add up to a whole second or two, then all of the other overhead (which Benchmark has to work hard to subtract from the above comparisons) usually adds up to several minutes and the difference is still imperceptible.

So, in those cases you should probably be studying the algorithm you are using or profiling the code rather than running benchmarks trying to prematurely optimize nano-operations such as these. (:

Update: BTW, the reason (or at least my educated guess at the reason) that this benchmark shows s/// being faster is because tr/// looks up every character in the map that it builds while, in this case, s/// can (more quickly) skip to the next character that it cares about.

- tye        

Replies are listed 'Best First'.
Re: Re: Difference between tr// and s///? (function not speed)
by kalamiti (Friar) on Feb 07, 2004 at 07:58 UTC
    thank you all, in one day I've learn much more than ever regarding all these Perl things.
      Indeed. It happens very often (like in this post) that I look at a post and say to myself "Oh, I know the answer to that!" Then I look at the answers and I'm absolutely blown away by the depth of other's knowledge.

      I find that Perlmonks makes me feel inadequete. I also find I always play a game of go after reading Perlmonks, to make me feel better about me ^_^.

      Fantastic responces everybody! ^_^