Кога да използвам 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: Hypertext Preprocessor"


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

Това се случва, защото:

  • 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
Струва си да се отбележи, че има 3 аргументен режим на strtr, в който единични знаци се транспонират директно 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 Manual Strtr.

person Arif RH    schedule 18.11.2011

Забележка в ръководството STRTR-- Описание низ strtr ( низ $str , низ $from , низ $to ) низ strtr ( низ $str , масив $replace_pairs ) Ако са дадени три аргумента, тази функция връща копие от улица, където...

STR_REPLACE-- ... Ако търсенето или замяната са масиви, техните елементи се обработват от първи до последен. ...

STRTR всеки ход НЕ влияе на следващия, НО STR_REPLACE го прави.

person Null None    schedule 18.09.2012