When to use strtr vs str_replace?
Asked Answered
N

4

95

I'm having a hard time understanding when strtr would be preferable to str_replace or vice versa. It seems that it's possible to achieve the exact same results using either function, although the order in which substrings are replaced is reversed. For example:

echo strtr('test string', 'st', 'XY')."\n";
echo strtr('test string', array( 's' => 'X', 't' => 'Y', 'st' => 'Z' ))."\n";
echo str_replace(array('s', 't', 'st'), array('X', 'Y', 'Z'), 'test string')."\n";
echo str_replace(array('st', 't', 's'), array('Z', 'Y', 'X'), 'test string');

This outputs

YeXY XYring
YeZ Zring
YeXY XYring
YeZ Zring

Aside from syntax, is there any benefit to using one over the other? Any cases where one would not be sufficient to achieve a desired result?

Nahum answered 18/11, 2011 at 3:13 Comment(1)
From a readability standpoint, strtr could easily be misread as strstr which is quite different. I'm starting to think I'm dyslexic. Won't make that mistake with str_replace.Erstwhile
F
152

First difference:

An interesting example of a different behaviour between strtr and str_replace is in the comments section of the PHP Manual:

<?php
$arrFrom = array("1","2","3","B");
$arrTo = array("A","B","C","D");
$word = "ZBB2";
echo str_replace($arrFrom, $arrTo, $word);
?>
  • I would expect as result: "ZDDB"
  • However, this return: "ZDDD" (Because B = D according to our array)

To make this work, use "strtr" instead:

<?php
$arr = array("1" => "A","2" => "B","3" => "C","B" => "D");
$word = "ZBB2";
echo strtr($word,$arr);
?>
  • This returns: "ZDDB"

This means that str_replace is a more global approach to replacements, while strtr simply translates the chars one by one.


Another difference:

Given the following code (taken from PHP String Replacement Speed Comparison):

<?php
$text = "PHP: Hypertext Preprocessor";

$text_strtr = strtr($text
    , array("PHP" => "PHP: Hypertext Preprocessor"
        , "PHP: Hypertext Preprocessor" => "PHP"));
$text_str_replace = str_replace(array("PHP", "PHP: Hypertext Preprocessor")
    , array("PHP: Hypertext Preprocessor", "PHP")
    , $text);
var_dump($text_strtr);
var_dump($text_str_replace);
?>

The resulting lines of text will be:

string(3) "PHP"
string(27) "PHP: Hypertext Preprocessor"


The main explanation:

This happens because:

  • strtr: it sorts its parameters by length, in descending order, so:

    1. it will give "more importance" to the largest one, and then, as the subject text is itself the largest key of the replacement array, it gets translated.
    2. because all the chars of the subject text have been replaced, the process ends there.
  • str_replace: it works in the order the keys are defined, so:

    1. it finds the key “PHP” in the subject text and replaces it with: “PHP: Hypertext Preprocessor”, what gives as result:

      “PHP: Hypertext Preprocessor: Hypertext Preprocessor”.

    2. then it finds the next key: “PHP: Hypertext Preprocessor” in the resulting text of the former step, so it gets replaced by "PHP", which gives as result:

      “PHP: Hypertext Preprocessor”.

    3. there are no more keys to look for, so the replacement ends there.

Fortenberry answered 18/11, 2011 at 3:26 Comment(6)
Ah ok thanks! I didn't realize strtr was translating by length - I thought it was in the reverse order.Nahum
As documented in php.net the function str_replace has 1 more paramerter named "count" to indicate how many time the replacement should perform. But I'm unable to use this parameter anyway. Does anyone know why ?Zoi
@vantrung-cuncon That isn't what that parameter is for. The docs say: "This will be set to the number of replacements performed." You will need to find another solution if you want to limit str_replace to a certain amount of replacements.Assign
Limiting the number of replacement may be useful if you want to replace the first occurrence of an acronym into the extended version, i.e. change the first occurence of "WHO" into "WHO (World Health Organization)".Promise
strtr won't replace text inserted by previous replacements. strtr('foo', array('oo' => 'ie', 'e' => 't')) returns 'fie' instead of 'fit' as str_replace does. Thus it automatically addresses the issue brought up by @Pies.Credent
It's worth noting that there is a 3 arg mode of strtr, in which single characters are transposed directly 1 to 1, and this doesn't involve any sorting by length... strtr('stack','abcde','12345') giving 'st13k'Dunois
E
24

It seems that it's possible to achieve the exact same results using either function

That's not always true and depends on the search and replace data you provide. For example where the two function differ see: Does PHP str_replace have a greater than 13 character limit?

  • strtr will not replace in parts of the string that already have been replaced - str_replace will replace inside replaces.
  • strtr will start with the longest key first in case you call it with two parameters - str_replace will replace from left to right.
  • str_replace can return the number of replacements done - strtr does not offer such a count value.
Edra answered 18/11, 2011 at 3:21 Comment(0)
F
7

I think strtr provides more flexible and conditional replacement when used with two arguments, for example: if string is 1, replace with a, but if string is 10, replace with b. This trick could only be achieved by strtr.

$string = "1.10.0001";  
echo strtr($string, array("1" => "a", "10" => "b"));  
// a.b.000a  

see : Php Manual Strtr.

Frederickfredericka answered 18/11, 2011 at 3:48 Comment(0)
C
2

Notice in manual STRTR-- Description string strtr ( string $str , string $from , string $to ) string strtr ( string $str , array $replace_pairs ) If given three arguments, this function returns a copy of str where ...

STR_REPLACE-- ... If search or replace are arrays, their elements are processed first to last. ...

STRTR each turn NOT effect to next, BUT STR_REPLACE does.

Cheboksary answered 18/9, 2012 at 21:30 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.