Замена букв одновременно с strtr

Я пытаюсь заменить строку одновременно с 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

П.С .: Я должен убедиться, что эти слова не являются частью другого слова. Вот почему белые пробелы есть. Например, слово «нет» является частью слова «никто», и если вы замените все «нет» в строке, оно также заменит слова типа «никто»;

0

Решение

Так что здесь происходит?

$text = " a b c ";
$text = strtr($text, array(" a " => " b ", " b " => " a ", " c " => " d "));

Сначала вы должны знать, что:

  1. Самые длинные ключи будут заменены первыми
  2. После замены он больше не ищет этот ключ

Так что здесь все ключи имеют одинаковую длину, значит, он заменит первый 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);

?>
5

Другие решения

Путь без 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,

0

По вопросам рекламы [email protected]