note 88569 added to function.str-replace
| From: | michael dot moussa at gmail dot com | Date: | Thu, 29 Jan 2009 14:38:46 +0000 |
| Subject: | note 88569 added to function.str-replace | ||
| Groups: | php.notes | ||
| Request: | Send a blank email to php-notes+get-149944@lists.php.net to get a copy of this message | ||
As previous commentators mentioned, when $search contains values that occur earlier in $replace,
str_replace will factor those previous replacements into the process rather than operating solely on
the original string. This may produce unexpected output.
Example:
<?php
$search = array('A', 'B', 'C', 'D', 'E');
$replace = array('B', 'C', 'D', 'E', 'F');
$subject = 'ABCDE';
echo str_replace($search, $replace, $subject); // output: 'FFFFFF'
?>
In the above code, the $search and $replace should replace each occurrence in the $subject with the
next letter in the alphabet. The expected output for this sample is 'BCDEF'; however, the
actual output is 'FFFFF'.
To more clearly illustrate this, consider the following example:
<?php
$search = array('A', 'B', 'C', 'D', 'E');
$replace = array('B', 'C', 'D', 'E', 'F');
$subject = 'A';
echo str_replace($search, $replace, $subject); // output: 'F'
?>
Since 'A' is the only letter in the $search array that appears in $subject, one would
expect the result to be 'B'; however, replacement number $n does *not* operate on
$subject, it operates on $subject after the previous $n-1 replacements have been completed.
The following function utilizes array_combine and strtr to produce the expected output, and I
believe it is the most efficient way to perform the desired string replacement without prior
replacements affecting the final result.
<?php
/**
* When using str_replace(...), values that did not exist in the original string (but were put there
by previous
* replacements) will be replaced continuously. This string replacement function is designed replace
the values
* in $search with those in $replace while not factoring in prior replacements. Note that this
function will
* always look for the longest possible match first and then work its way down to individual
characters.
*
* The "o" in "stro_replace" represents "original", indicating that the
function operates only on the original string.
*
* @param array $search list of strings or characters that need to be replaced
* @param array $replace list of strings or characters that will replace the corresponding values in
$search
* @param string $subject the string on which this operation is being performed
*
* @return string $subject with all substrings in the $search array replaced by the values in the
$replace array
*/
function stro_replace($search, $replace, $subject)
{
return strtr( $subject, array_combine($search, $replace) );
}
$search = array('A', 'B', 'C', 'D', 'E');
$replace = array('B', 'C', 'D', 'E', 'F');
$subject = 'ABCDE';
echo stro_replace($search, $replace, $subject); // output: 'BCDEF'
?>
Some other examples:
<?php
$search = array(' ', '&');
$replace = array(' ', '&');
$subject = 'Hello & goodbye!';
// We want to replace the spaces with and the ampersand with &
echo str_replace($search, $replace, $subject); // output:
"Hello&nbsp&&nbspgoodbye!" - wrong!
echo stro_replace($search, $replace, $subject); // output:
"Hello & goodbye!" - correct!
/*
Note: Run the above code in the CLI or view source on your web browser - the replacement
strings for stro_replace are HTML entities which the browser interprets.
*/
?>
<?php
$search = array('ERICA', 'AMERICA');
$replace = array('JON', 'PHP');
$subject = 'MIKE AND ERICA LIKE AMERICA';
// We want to replace the name "ERICA" with "JON" and the word
"AMERICA" with "PHP"
echo str_replace($search, $replace, $subject); // output: "MIKE AND JON LIKE AMJON", which
is not correct
echo stro_replace($search, $replace, $subject); // output: "MIKE AND JON LIKE PHP", which
is correct
?>
----
Server IP: 69.147.83.197
Probable Submitter: 216.177.196.194
----
Manual Page -- http://www.php.net/manual/en/function.str-replace.php
Edit -- https://master.php.net/note/edit/88569
Del: integrated -- https://master.php.net/note/delete/88569/integrated
Del: useless -- https://master.php.net/note/delete/88569/useless
Del: bad code -- https://master.php.net/note/delete/88569/bad+code
Del: spam -- https://master.php.net/note/delete/88569/spam
Del: non-english -- https://master.php.net/note/delete/88569/non-english
Del: in docs -- https://master.php.net/note/delete/88569/in+docs
Del: other reasons-- https://master.php.net/note/delete/88569
Reject -- https://master.php.net/note/reject/88569
Search -- https://master.php.net/manage/user-notes.php