I'm trying to replace a string simultaneously with strtr but I came across a problem. If the letter being replaced simultaneously is next to another letter that is being replaced simultaneously it doesn't replace the letter after the first letter. What can I do to fix this? Thanks.
$text = " no bacon cats nobody ";
$text = strtr($text, array(" no " => " bacon ", " bacon " => " no ", " cats " => " dogs "));
echo $text;
Expected Results
bacon no dogs nobody
Actual Results
bacon bacon dogs nobody
P.S: I have to make sure those words aren't part of another word. That's why the white spaces are there. For example, the word "no" is part of "nobody", and if you replaced all "no" in the string, it would also replace words like "nobody";
So what happens here?
$text = " a b c ";
$text = strtr($text, array(" a " => " b ", " b " => " a ", " c " => " d "));
First you have to know that:
So here all keys have the same length, means it will replace the first key => value
element, then the second and so on.
So first " a " => " b "
will be replaced, which will change your start string:
a b c
↑↑↑ Match
to this:
b b c
↑↑↑ Replacement
Remember how we said, after replacing the values it doesn't search for it anymore? Exactly! Now it searches for " b " => " a "
, but only in this part of the string:
ab c
So it won't find it, since there is no space in front of the b to search for. That's why you don't get your expected output. And c
will be found again, since it has a space in front of it.
So the problem here in your code is, that it doesn't include replaced values in the search of the next key. Even if [space]b[space]
is in your string, it doesn't find it, since the first space is from the replaced value of the key [space]a[space]
, which won't be included in the next search.
EDIT:
As from your updated question it seems that you have done this to try to prevent words be part of other words. To solve this simply make a lookup array and use preg_replace_callback()
with word boundarys to match only full words and not only a part of it, e.g.
<?php
$text = " apple bacon cats ";
$replacement = ["apple" => "bacon", "bacon" => "apple", "cats" => "dogs"];
$search = array_map(function($v){
return preg_quote($v, "/");
}, array_keys($replacement));
echo $text = preg_replace_callback("/\b(" . implode("|", $search) . ")\b/", function($m)use($replacement){
return $replacement[$m[1]];
}, $text);
?>