Когда использовать strtr vs str_replace?

86

Мне сложно понять, когда strtrлучше str_replaceили наоборот. Кажется, что можно достичь тех же результатов, используя любую функцию, хотя порядок, в котором заменяются подстроки, обратный. Например:

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');

Это выводит

YeXY XYring
YeZ Zring
YeXY XYring
YeZ Zring

Помимо синтаксиса, есть ли преимущества в использовании одного над другим? Есть ли случаи, когда одного было бы недостаточно для достижения желаемого результата?

Эндрютвебер
источник
3
С точки зрения удобочитаемости, strtrможет быть легко неправильно истолковано, strstrчто совсем другое. Я начинаю думать, что я дислексик. Не допустите такой ошибки с str_replace.
Программист

Ответы:

135

Первое отличие:

Интересный пример различного поведения между strtrи str_replaceнаходится в разделе комментариев Руководства по PHP:

<?php
$arrFrom = array("1","2","3","B");
$arrTo = array("A","B","C","D");
$word = "ZBB2";
echo str_replace($arrFrom, $arrTo, $word);
?>
  • Я ожидал в результате: "ZDDB"
  • Однако этот возврат: "ZDDD" (потому что B = D согласно нашему массиву)

Чтобы это сработало, используйте вместо этого "strtr":

<?php
$arr = array("1" => "A","2" => "B","3" => "C","B" => "D");
$word = "ZBB2";
echo strtr($word,$arr);
?>
  • Это возвращает: "ZDDB"

Это означает, что str_replaceэто более глобальный подход к заменам, при котором strtrсимволы просто переводятся один за другим.


Еще одно отличие:

Учитывая следующий код (взятый из сравнения скорости замены строк PHP ):

<?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);
?>

В результате появятся следующие строки текста:

строка (3) «PHP»
строка (27) «PHP: препроцессор гипертекста»


Основное объяснение:

Это происходит потому, что:

  • strtr : он сортирует свои параметры по длине в порядке убывания, поэтому:

    1. он придаст «большее значение» самому большому из них, а затем, поскольку предметный текст сам по себе является самым большим ключом замещающего массива, он будет переведен.
    2. поскольку все символы текста темы были заменены, процесс на этом заканчивается.
  • str_replace : он работает в том порядке, в котором определены ключи, поэтому:

    1. он находит ключ «PHP» в тексте темы и заменяет его на «PHP: препроцессор гипертекста», что дает в результате:

      «PHP: Препроцессор гипертекста: Препроцессор гипертекста».

    2. затем он находит следующий ключ: «PHP: препроцессор гипертекста» в результирующем тексте предыдущего шага, поэтому он заменяется на «PHP», что дает в результате:

      «PHP: препроцессор гипертекста».

    3. ключей больше нет, поэтому замена на этом заканчивается.

Николас Озимица
источник
2
Ах хорошо, спасибо! Я не понимал, что strtr переводит по длине - я думал, что это было в обратном порядке.
andrewtweber
Как описано в php.net, функция str_replace имеет еще 1 параметр с именем «count», чтобы указать, сколько раз должна выполняться замена. Но я все равно не могу использовать этот параметр. Кто-нибудь знает почему?
vantrung -cuncon
1
@ vantrung-cuncon Этот параметр не для этого. Документы говорят: «Это будет установлено на количество выполненных замен». Вам нужно будет найти другое решение, если вы хотите ограничить str_replace определенным количеством замен.
jdhartley
1
Ограничение количества замен может быть полезно, если вы хотите заменить первое вхождение акронима в расширенную версию, то есть изменить первое вхождение «ВОЗ» на «ВОЗ (Всемирная организация здравоохранения)».
Michał Tatarynowicz
strtrне заменяет текст, вставленный предыдущими заменами. strtr('foo', array('oo' => 'ie', 'e' => 't'))возвращает 'fie'вместо , 'fit'как str_replaceделает. Таким образом, он автоматически решает проблему, поднятую @Pies.
Дэвид Харкнесс
21

Кажется, что можно достичь тех же результатов, используя любую функцию

Это не всегда так и зависит от данных поиска и замены, которые вы предоставляете. Например, где эти две функции различаются, см .: Имеет ли PHP str_replace ограничение более 13 символов?

  • strtrне будет заменять в частях строки, которые уже были заменены - str_replaceзаменит внутри заменяет.
  • strtrсначала будет начинаться с самого длинного ключа, если вы вызываете его с двумя параметрами - str_replaceбудет заменять слева направо.
  • str_replaceможет возвращать количество выполненных замен - strtrне предлагает такое значение счетчика.
hakre
источник
7

Я думаю, strtrобеспечивает более гибкую и условную замену при использовании с двумя аргументами, например: если строка равна 1, заменить на a, а если строка равна 10, заменить на b. Этого трюка можно было достичь только с помощью strtr.

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

см .: Руководство по Php Strtr .

Ариф РХ
источник
2

Примечание в руководстве STRTR - Описание string strtr (string $ str, string $ from, string $ to) string strtr (string $ str, array $ replace_pairs) Если задано три аргумента, эта функция возвращает копию str, где ...

STR_REPLACE-- ... Если поиск или замена являются массивами, их элементы обрабатываются с начала до конца . ...

STRTR каждый ход НЕ влияет на следующий, НО STR_REPLACE действует.

Null Нет
источник