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

Мне трудно понять, когда 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

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


person andrewtweber    schedule 18.11.2011    source источник
comment
С точки зрения удобочитаемости, strtr можно легко принять за strstr, что сильно отличается. Я начинаю думать, что у меня дислексия. Не совершите эту ошибку с помощью str_replace.   -  person Programster    schedule 23.08.2015


Ответы (4)


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

Интересный пример различного поведения между 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);
?>

Результирующие строки текста будут такими:

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


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

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

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

    1. it will give "more importance" to the largest one, and then, as the subject text is itself the largest key of the replacement array, it gets translated.
    2. поскольку все символы текста темы были заменены, процесс на этом заканчивается.
  • str_replace: работает в порядке определения ключей, поэтому:

    1. it finds the key “PHP” in the subject text and replaces it with: “PHP: Hypertext Preprocessor”, what gives as result:

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

    2. #P14# <блочная цитата> #P15#
    3. ключей искать больше нечего, поэтому замена на этом заканчивается.

person Nicolás Ozimica    schedule 18.11.2011
comment
Ок спасибо! Я не знал, что strtr переводит по длине - я думал, что это было в обратном порядке. - person andrewtweber; 18.11.2011
comment
Как описано в php.net, функция str_replace имеет еще 1 параметр с именем count, чтобы указать, сколько раз должна выполняться замена. Но я все равно не могу использовать этот параметр. Кто-нибудь знает, почему? - person vantrung -cuncon; 25.03.2012
comment
@ vantrung-cuncon Этот параметр предназначен не для этого. Документы говорят: это будет установлено на количество выполненных замен. Вам нужно будет найти другое решение, если вы хотите ограничить str_replace определенным количеством замен. - person jdhartley; 23.04.2012
comment
Ограничение количества замен может быть полезным, если вы хотите заменить первое вхождение аббревиатуры на расширенную версию, т. е. изменить первое вхождение ВОЗ на ВОЗ (Всемирная организация здравоохранения). - person Michał Tatarynowicz; 19.01.2013
comment
strtr не заменяет текст, вставленный предыдущими заменами. strtr('foo', array('oo' => 'ie', 'e' => 't')) возвращает 'fie' вместо 'fit', как это делает str_replace. Таким образом, он автоматически решает проблему, поднятую @Pies. - person David Harkness; 30.01.2014
comment
Стоит отметить, что существует режим strtr с 3 аргументами, в котором отдельные символы транспонируются напрямую от 1 к 1, и это не требует сортировки по длине... strtr('stack','abcde','12345' ) дает 'st13k' - person Gavin Jackson; 13.12.2018

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

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

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

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

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

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

person Arif RH    schedule 18.11.2011

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

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

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

person Null None    schedule 18.09.2012