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        


In reply to Re: Difference between tr// and s///? (function not speed) by tye
in thread Difference between tr/// and s///? by kalamiti

Title:
Use:  <p> text here (a paragraph) </p>
and:  <code> code here </code>
to format your post, it's "PerlMonks-approved HTML":



  • Posts are HTML formatted. Put <p> </p> tags around your paragraphs. Put <code> </code> tags around your code and data!
  • Titles consisting of a single word are discouraged, and in most cases are disallowed outright.
  • Read Where should I post X? if you're not absolutely sure you're posting in the right place.
  • Please read these before you post! —
  • Posts may use any of the Perl Monks Approved HTML tags:
    a, abbr, b, big, blockquote, br, caption, center, col, colgroup, dd, del, details, div, dl, dt, em, font, h1, h2, h3, h4, h5, h6, hr, i, ins, li, ol, p, pre, readmore, small, span, spoiler, strike, strong, sub, summary, sup, table, tbody, td, tfoot, th, thead, tr, tt, u, ul, wbr
  • You may need to use entities for some characters, as follows. (Exception: Within code tags, you can put the characters literally.)
            For:     Use:
    & &amp;
    < &lt;
    > &gt;
    [ &#91;
    ] &#93;
  • Link using PerlMonks shortcuts! What shortcuts can I use for linking?
  • See Writeup Formatting Tips and other pages linked from there for more info.