Я пытаюсь заменить строку одновременно с strtr, но я столкнулся с проблемой. Если буква, заменяемая одновременно, находится рядом с другой буквой, которая заменяется одновременно, она не заменяет букву после первой буквы. Что я могу сделать, чтобы это исправить? Благодарю.
$text = " no bacon cats nobody ";
$text = strtr($text, array(" no " => " bacon ", " bacon " => " no ", " cats " => " dogs "));
echo $text;
Ожидаемые результаты
bacon no dogs nobody
Фактические результаты
bacon bacon dogs nobody
П.С .: Я должен убедиться, что эти слова не являются частью другого слова. Вот почему белые пробелы есть. Например, слово «нет» является частью слова «никто», и если вы замените все «нет» в строке, оно также заменит слова типа «никто»;
Так что здесь происходит?
$text = " a b c ";
$text = strtr($text, array(" a " => " b ", " b " => " a ", " c " => " d "));
Сначала вы должны знать, что:
Так что здесь все ключи имеют одинаковую длину, значит, он заменит первый key => value
элемент, потом второй и тд.
Итак, сначала " a " => " b "
будет заменено, что изменит вашу стартовую строку:
a b c
↑↑↑ Match
к этому:
b b c
↑↑↑ Replacement
Помните, как мы сказали, после замены значений он больше не ищет? Именно так! Сейчас он ищет " b " => " a "
, но только в этой части строки:
До нашей эры
Так что он не найдет его, так как перед b нет места для поиска. Вот почему вы не получите ожидаемый результат. А также c
будет найден снова, так как у него есть место перед ним.
Итак, проблема здесь в вашем коде в том, что он не включает замененные значения в поиске следующего ключа. Даже если [space]b[space]
находится в вашей строке, он не находит его, так как первый пробел от замененного значения ключа [space]a[space]
, который не будет включен в следующий поиск.
РЕДАКТИРОВАТЬ:
Из вашего обновленного вопроса кажется, что вы сделали это, чтобы не дать словам быть частью других слов. Чтобы решить эту проблему, просто создайте массив поиска и используйте preg_replace_callback()
с границами слов, чтобы соответствовать только полным словам, а не только их части, например
<?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);
?>
Путь без strtr:
$text = 'no bacon cats nobody';
$rep = ['no'=>'bacon', 'bacon'=>'no', 'cats'=>'dogs'];
$parts = explode(' ', $text);
foreach ($parts as &$part) {
if (isset($rep[$part]))
$part = $rep[$part];
}
$result = implode(' ', $parts);
если вы хотите что-то более гибкое, замените explode
линия с:
$parts = preg_split('~\b~', $parts);
и использовать пустую строку с implode
,